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:
Richard Schneider 2018-01-31 07:41:18 +13:00 committed by silverwind
parent 140ea5c229
commit d58cdb3419
3 changed files with 111 additions and 12 deletions

View File

@ -132,10 +132,14 @@ Currently the different available records are
``` 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`
``` js

View File

@ -284,13 +284,81 @@ rsoa.encodingLength = function (data) {
return 22 + name.encodingLength(data.mname) + name.encodingLength(data.rname)
}
const rtxt = exports.txt = exports.null = {}
const rnull = rtxt
const rtxt = exports.txt = {}
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 (!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 (!data) data = Buffer.allocUnsafe(0)
@ -302,13 +370,13 @@ rtxt.encode = function (data, buf, offset) {
offset += len
buf.writeUInt16BE(offset - oldOffset - 2, oldOffset)
rtxt.encode.bytes = offset - oldOffset
rnull.encode.bytes = offset - oldOffset
return buf
}
rtxt.encode.bytes = 0
rnull.encode.bytes = 0
rtxt.decode = function (buf, offset) {
rnull.decode = function (buf, offset) {
if (!offset) offset = 0
const oldOffset = offset
const len = buf.readUInt16BE(offset)
@ -318,13 +386,13 @@ rtxt.decode = function (buf, offset) {
const data = buf.slice(offset, offset + len)
offset += len
rtxt.decode.bytes = offset - oldOffset
rnull.decode.bytes = offset - oldOffset
return data
}
rtxt.decode.bytes = 0
rnull.decode.bytes = 0
rtxt.encodingLength = function (data) {
rnull.encodingLength = function (data) {
if (!data) return 2
return (Buffer.isBuffer(data) ? data.length : Buffer.byteLength(data)) + 2
}

33
test.js
View File

@ -12,9 +12,36 @@ tape('unknown', function (t) {
})
tape('txt', function (t) {
testEncoder(t, packet.txt, Buffer.allocUnsafe(0))
testEncoder(t, packet.txt, Buffer.from('hello world'))
testEncoder(t, packet.txt, Buffer.from([0, 1, 2, 3, 4, 5]))
testEncoder(t, packet.txt, [])
testEncoder(t, packet.txt, ['hello world'])
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()
})