1
|
'use strict'
|
2
|
|
3
|
var bindexOf = require('buffer-indexof')
|
4
|
|
5
|
var equalSign = new Buffer('=')
|
6
|
|
7
|
module.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
|
|
88
|
function 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
|
}
|