UNPKG

2.6 kBJavaScriptView Raw
1'use strict'
2
3var bindexOf = require('buffer-indexof')
4
5var equalSign = new Buffer('=')
6
7module.exports = function (opts) {
8 var binary = opts ? opts.binary : false
9 var that = {}
10
11 that.encode = function (data, buf, offset) {
12 if (!data) data = {}
13 if (!offset) offset = 0
14 if (!buf) buf = new Buffer(that.encodingLength(data) + offset)
15
16 var oldOffset = offset
17 var keys = Object.keys(data)
18
19 if (keys.length === 0) {
20 buf[offset] = 0
21 offset++
22 }
23
24 keys.forEach(function (key) {
25 var val = data[key]
26 var oldOffset = offset
27 offset++
28
29 if (val === true) {
30 offset += buf.write(key, offset)
31 } else if (Buffer.isBuffer(val)) {
32 offset += buf.write(key + '=', offset)
33 var len = val.length
34 val.copy(buf, offset, 0, len)
35 offset += len
36 } else {
37 offset += buf.write(key + '=' + val, offset)
38 }
39
40 buf[oldOffset] = offset - oldOffset - 1
41 })
42
43 that.encode.bytes = offset - oldOffset
44 return buf
45 }
46
47 that.decode = function (buf, offset, len) {
48 if (!offset) offset = 0
49 if (!Number.isFinite(len)) len = buf.length
50 var data = {}
51 var oldOffset = offset
52
53 while (offset < len) {
54 var b = decodeBlock(buf, offset)
55 var i = bindexOf(b, equalSign)
56 offset += decodeBlock.bytes
57
58 if (b.length === 0) continue // ignore: most likely a single zero byte
59 if (i === -1) data[b.toString().toLowerCase()] = true
60 else if (i === 0) continue // ignore: invalid key-length
61 else {
62 var key = b.slice(0, i).toString().toLowerCase()
63 if (key in data) continue // ignore: overwriting not allowed
64 data[key] = binary ? b.slice(i + 1) : b.slice(i + 1).toString()
65 }
66 }
67
68 that.decode.bytes = offset - oldOffset
69 return data
70 }
71
72 that.encodingLength = function (data) {
73 if (!data) return 1 // 1 byte (single empty byte)
74 var keys = Object.keys(data)
75 if (keys.length === 0) return 1 // 1 byte (single empty byte)
76 return keys.reduce(function (total, key) {
77 var val = data[key]
78 total += Buffer.byteLength(key) + 1 // +1 byte to store field length
79 if (Buffer.isBuffer(val)) total += val.length + 1 // +1 byte to fit equal sign
80 else if (val !== true) total += Buffer.byteLength(String(val)) + 1 // +1 byte to fit equal sign
81 return total
82 }, 0)
83 }
84
85 return that
86}
87
88function decodeBlock (buf, offset) {
89 var len = buf[offset]
90 var to = offset + 1 + len
91 var b = buf.slice(offset + 1, to > buf.length ? buf.length : to)
92 decodeBlock.bytes = len + 1
93 return b
94}