forked from LittleChest/dns-packet
Change TXT values to array of buffers (breaking) (#26)
* fix: txt data is an array of strings * fix: a consistent API for TXT data * docs: update TXT info * feat: empty buffer is not allowed * fix: allow empty strings and buffers * fix: rnull is like old rtxt
This commit is contained in:
parent
140ea5c229
commit
d58cdb3419
@ -132,10 +132,14 @@ Currently the different available records are
|
|||||||
|
|
||||||
``` js
|
``` js
|
||||||
{
|
{
|
||||||
data: Buffer('some text')
|
data: 'text' || Buffer || [ Buffer || 'text' ]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
When encoding, scalar values are converted to an array and strings are converted to UTF-8 encoded Buffers. An error is `thrown` if a string or Buffer is empty.
|
||||||
|
|
||||||
|
When decoding, an array of Buffer is always returned.
|
||||||
|
|
||||||
#### `NS`
|
#### `NS`
|
||||||
|
|
||||||
``` js
|
``` js
|
||||||
|
|||||||
84
index.js
84
index.js
@ -284,13 +284,81 @@ rsoa.encodingLength = function (data) {
|
|||||||
return 22 + name.encodingLength(data.mname) + name.encodingLength(data.rname)
|
return 22 + name.encodingLength(data.mname) + name.encodingLength(data.rname)
|
||||||
}
|
}
|
||||||
|
|
||||||
const rtxt = exports.txt = exports.null = {}
|
const rtxt = exports.txt = {}
|
||||||
const rnull = rtxt
|
|
||||||
|
|
||||||
rtxt.encode = function (data, buf, offset) {
|
rtxt.encode = function (data, buf, offset) {
|
||||||
|
if (!Array.isArray(data)) data = [data]
|
||||||
|
for (let i = 0; i < data.length; i++) {
|
||||||
|
if (typeof data[i] === 'string') {
|
||||||
|
data[i] = Buffer.from(data[i])
|
||||||
|
}
|
||||||
|
if (!Buffer.isBuffer(data[i])) {
|
||||||
|
throw new Error('Must be a Buffer')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!buf) buf = Buffer.allocUnsafe(rtxt.encodingLength(data))
|
if (!buf) buf = Buffer.allocUnsafe(rtxt.encodingLength(data))
|
||||||
if (!offset) offset = 0
|
if (!offset) offset = 0
|
||||||
|
|
||||||
|
const oldOffset = offset
|
||||||
|
offset += 2
|
||||||
|
|
||||||
|
data.forEach(function (d) {
|
||||||
|
buf[offset++] = d.length
|
||||||
|
d.copy(buf, offset, 0, d.length)
|
||||||
|
offset += d.length
|
||||||
|
})
|
||||||
|
|
||||||
|
buf.writeUInt16BE(offset - oldOffset - 2, oldOffset)
|
||||||
|
rtxt.encode.bytes = offset - oldOffset
|
||||||
|
return buf
|
||||||
|
}
|
||||||
|
|
||||||
|
rtxt.encode.bytes = 0
|
||||||
|
|
||||||
|
rtxt.decode = function (buf, offset) {
|
||||||
|
if (!offset) offset = 0
|
||||||
|
const oldOffset = offset
|
||||||
|
let remaining = buf.readUInt16BE(offset)
|
||||||
|
offset += 2
|
||||||
|
|
||||||
|
let data = []
|
||||||
|
while (remaining > 0) {
|
||||||
|
const len = buf[offset++]
|
||||||
|
--remaining
|
||||||
|
if (remaining < len) {
|
||||||
|
throw new Error('Buffer overflow')
|
||||||
|
}
|
||||||
|
data.push(buf.slice(offset, offset + len))
|
||||||
|
offset += len
|
||||||
|
remaining -= len
|
||||||
|
}
|
||||||
|
|
||||||
|
rtxt.decode.bytes = offset - oldOffset
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
rtxt.decode.bytes = 0
|
||||||
|
|
||||||
|
rtxt.encodingLength = function (data) {
|
||||||
|
if (!Array.isArray(data)) data = [data]
|
||||||
|
let length = 2
|
||||||
|
data.forEach(function (buf) {
|
||||||
|
if (typeof buf === 'string') {
|
||||||
|
length += Buffer.byteLength(buf) + 1
|
||||||
|
} else {
|
||||||
|
length += buf.length + 1
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return length
|
||||||
|
}
|
||||||
|
|
||||||
|
const rnull = exports.null = {}
|
||||||
|
|
||||||
|
rnull.encode = function (data, buf, offset) {
|
||||||
|
if (!buf) buf = Buffer.allocUnsafe(rnull.encodingLength(data))
|
||||||
|
if (!offset) offset = 0
|
||||||
|
|
||||||
if (typeof data === 'string') data = Buffer.from(data)
|
if (typeof data === 'string') data = Buffer.from(data)
|
||||||
if (!data) data = Buffer.allocUnsafe(0)
|
if (!data) data = Buffer.allocUnsafe(0)
|
||||||
|
|
||||||
@ -302,13 +370,13 @@ rtxt.encode = function (data, buf, offset) {
|
|||||||
offset += len
|
offset += len
|
||||||
|
|
||||||
buf.writeUInt16BE(offset - oldOffset - 2, oldOffset)
|
buf.writeUInt16BE(offset - oldOffset - 2, oldOffset)
|
||||||
rtxt.encode.bytes = offset - oldOffset
|
rnull.encode.bytes = offset - oldOffset
|
||||||
return buf
|
return buf
|
||||||
}
|
}
|
||||||
|
|
||||||
rtxt.encode.bytes = 0
|
rnull.encode.bytes = 0
|
||||||
|
|
||||||
rtxt.decode = function (buf, offset) {
|
rnull.decode = function (buf, offset) {
|
||||||
if (!offset) offset = 0
|
if (!offset) offset = 0
|
||||||
const oldOffset = offset
|
const oldOffset = offset
|
||||||
const len = buf.readUInt16BE(offset)
|
const len = buf.readUInt16BE(offset)
|
||||||
@ -318,13 +386,13 @@ rtxt.decode = function (buf, offset) {
|
|||||||
const data = buf.slice(offset, offset + len)
|
const data = buf.slice(offset, offset + len)
|
||||||
offset += len
|
offset += len
|
||||||
|
|
||||||
rtxt.decode.bytes = offset - oldOffset
|
rnull.decode.bytes = offset - oldOffset
|
||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
|
|
||||||
rtxt.decode.bytes = 0
|
rnull.decode.bytes = 0
|
||||||
|
|
||||||
rtxt.encodingLength = function (data) {
|
rnull.encodingLength = function (data) {
|
||||||
if (!data) return 2
|
if (!data) return 2
|
||||||
return (Buffer.isBuffer(data) ? data.length : Buffer.byteLength(data)) + 2
|
return (Buffer.isBuffer(data) ? data.length : Buffer.byteLength(data)) + 2
|
||||||
}
|
}
|
||||||
|
|||||||
33
test.js
33
test.js
@ -12,9 +12,36 @@ tape('unknown', function (t) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
tape('txt', function (t) {
|
tape('txt', function (t) {
|
||||||
testEncoder(t, packet.txt, Buffer.allocUnsafe(0))
|
testEncoder(t, packet.txt, [])
|
||||||
testEncoder(t, packet.txt, Buffer.from('hello world'))
|
testEncoder(t, packet.txt, ['hello world'])
|
||||||
testEncoder(t, packet.txt, Buffer.from([0, 1, 2, 3, 4, 5]))
|
testEncoder(t, packet.txt, ['hello', 'world'])
|
||||||
|
testEncoder(t, packet.txt, [Buffer.from([0, 1, 2, 3, 4, 5])])
|
||||||
|
testEncoder(t, packet.txt, ['a', 'b', Buffer.from([0, 1, 2, 3, 4, 5])])
|
||||||
|
testEncoder(t, packet.txt, ['', Buffer.allocUnsafe(0)])
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
|
|
||||||
|
tape('txt-scalar-string', function (t) {
|
||||||
|
const buf = packet.txt.encode('hi')
|
||||||
|
const val = packet.txt.decode(buf)
|
||||||
|
t.ok(val.length === 1, 'array length')
|
||||||
|
t.ok(val[0].toString() === 'hi', 'data')
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
|
|
||||||
|
tape('txt-scalar-buffer', function (t) {
|
||||||
|
const data = Buffer.from([0, 1, 2, 3, 4, 5])
|
||||||
|
const buf = packet.txt.encode(data)
|
||||||
|
const val = packet.txt.decode(buf)
|
||||||
|
t.ok(val.length === 1, 'array length')
|
||||||
|
t.ok(val[0].equals(data), 'data')
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
|
|
||||||
|
tape('txt-invalid-data', function (t) {
|
||||||
|
t.throws(function () { packet.txt.encode(null) }, 'null')
|
||||||
|
t.throws(function () { packet.txt.encode(undefined) }, 'undefined')
|
||||||
|
t.throws(function () { packet.txt.encode(10) }, 'number')
|
||||||
t.end()
|
t.end()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user