Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions packages/parser-packet-length/lib/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,4 +90,45 @@ describe('DelimiterParser', () => {
assert.deepEqual(spy.getCall(1).args[0], Buffer.concat([Buffer.from([0xaa, 0x02, 0x13, 0x00]), Buffer.from('Each and Every One\n')]))
assert(spy.calledTwice)
})

it('works with multiple delimiters', () => {
const spy = sinon.spy()
const parser = new PacketLengthParser({ delimiter: [0xaa, 0xbb], lengthOffset: 2, packetOverhead: 4, lengthBytes: 2 })
parser.on('data', spy)
parser.write(Buffer.from('\xbb\x01\x0d'))
parser.write(Buffer.from('\x00I love hobits\xaa\x02\x13\x00Each '))
parser.write(Buffer.from('and Every One\n'))

assert.deepEqual(spy.getCall(0).args[0], Buffer.concat([Buffer.from([0xbb, 0x01, 0x0d, 0x00]), Buffer.from('I love hobits')]))
assert.deepEqual(spy.getCall(1).args[0], Buffer.concat([Buffer.from([0xaa, 0x02, 0x13, 0x00]), Buffer.from('Each and Every One\n')]))
assert(spy.calledTwice)
})

it('works with multibyte delimiters', () => {
const spy = sinon.spy()
const parser = new PacketLengthParser({ delimiter: [0xababba], delimiterBytes: 3, lengthOffset: 3, packetOverhead: 4, lengthBytes: 1 })
parser.on('data', spy)
parser.write(Buffer.from([0xab, 0xab, 0xba, 0x0d]))
parser.write(Buffer.from('I love hobits'))
parser.write(Buffer.from([0xab, 0xab, 0xba, 0x13]))
parser.write(Buffer.from('Each and Every One\n'))

assert.deepEqual(spy.getCall(0).args[0], Buffer.concat([Buffer.from([0xab, 0xab, 0xba, 0x0d]), Buffer.from('I love hobits')]))
assert.deepEqual(spy.getCall(1).args[0], Buffer.concat([Buffer.from([0xab, 0xab, 0xba, 0x13]), Buffer.from('Each and Every One\n')]))
assert(spy.calledTwice)
})

it('works with multiple multibyte delimiters', () => {
const spy = sinon.spy()
const parser = new PacketLengthParser({ delimiter: [0xababba, 0xbaddad], delimiterBytes: 3, lengthOffset: 3, packetOverhead: 4, lengthBytes: 1 })
parser.on('data', spy)
parser.write(Buffer.from([0xab, 0xab, 0xba, 0x0d]))
parser.write(Buffer.from('I love hobits'))
parser.write(Buffer.from([0xba, 0xdd, 0xad, 0x13]))
parser.write(Buffer.from('Each and Every One\n'))

assert.deepEqual(spy.getCall(0).args[0], Buffer.concat([Buffer.from([0xab, 0xab, 0xba, 0x0d]), Buffer.from('I love hobits')]))
assert.deepEqual(spy.getCall(1).args[0], Buffer.concat([Buffer.from([0xba, 0xdd, 0xad, 0x13]), Buffer.from('Each and Every One\n')]))
assert(spy.calledTwice)
})
})
29 changes: 19 additions & 10 deletions packages/parser-packet-length/lib/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { Transform, TransformCallback, TransformOptions } from 'stream'

export interface PacketLengthOptions extends TransformOptions {
/** delimiter to use defaults to 0xaa */
delimiter?: number
/** delimiter(s) to use defaults to 0xaa */
delimiter?: number | number[]
/** delimiter length in bytes defaults to 1 */
delimiterBytes?: number
/** overhead of packet (including length, delimiter and any checksum / packet footer) defaults to 2 */
packetOverhead?: number
/** number of bytes containing length defaults to 1 */
Expand All @@ -29,14 +31,15 @@ export interface PacketLengthOptions extends TransformOptions {
export class PacketLengthParser extends Transform {
buffer: Buffer
start: boolean
opts: { delimiter: number, packetOverhead: number, lengthBytes: number, lengthOffset: number, maxLen: number }
opts: { delimiter: number[], delimiterBytes: number, packetOverhead: number, lengthBytes: number, lengthOffset: number, maxLen: number }
constructor(options: PacketLengthOptions = {}) {
super(options)

const { delimiter = 0xaa, packetOverhead = 2, lengthBytes = 1, lengthOffset = 1, maxLen = 0xff } = options
const { delimiter = [0xaa], delimiterBytes = 1, packetOverhead = 2, lengthBytes = 1, lengthOffset = 1, maxLen = 0xff } = options

this.opts = {
delimiter,
delimiter: ([] as number[]).concat(delimiter),
delimiterBytes,
packetOverhead,
lengthBytes,
lengthOffset,
Expand All @@ -51,13 +54,8 @@ export class PacketLengthParser extends Transform {
for (let ndx = 0; ndx < chunk.length; ndx++) {
const byte = chunk[ndx]

if (byte === this.opts.delimiter) {
this.start = true
}

if (true === this.start) {
this.buffer = Buffer.concat([this.buffer, Buffer.from([byte])])

if (this.buffer.length >= this.opts.lengthOffset + this.opts.lengthBytes) {
const len = this.buffer.readUIntLE(this.opts.lengthOffset, this.opts.lengthBytes)

Expand All @@ -67,6 +65,17 @@ export class PacketLengthParser extends Transform {
this.start = false
}
}
} else {
this.buffer = Buffer.concat([Buffer.from([byte]), this.buffer])
if (this.buffer.length === this.opts.delimiterBytes) {
const delimiter = this.buffer.readUIntLE(0, this.opts.delimiterBytes)
if (this.opts.delimiter.includes(delimiter)) {
this.start = true
this.buffer = Buffer.from([...this.buffer].reverse())
} else {
this.buffer = Buffer.from(this.buffer.subarray(1, this.buffer.length))
}
}
}
}

Expand Down
18 changes: 9 additions & 9 deletions packages/parser-start-end/lib/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ describe('StartEndParser', () => {
parser.write(Buffer.from(`${STX}I love robots${ETX}${STX}Each `))
parser.write(Buffer.from(`and Every One${ETX}`))
parser.write(Buffer.from(STX))
parser.write(Buffer.from(`even you!`))
parser.write(Buffer.from('even you!'))

assert.deepEqual(spy.getCall(0).args[0], Buffer.from('I love robots'))
assert.deepEqual(spy.getCall(1).args[0], Buffer.from('Each and Every One'))
Expand All @@ -35,7 +35,7 @@ describe('StartEndParser', () => {
parser.write(Buffer.from(`${STX}I love robots${ETX}${STX}Each `))
parser.write(Buffer.from(`and Every One${ETX}`))
parser.write(Buffer.from(STX))
parser.write(Buffer.from(`even you!`))
parser.write(Buffer.from('even you!'))

assert.deepEqual(spy.getCall(0).args[0], Buffer.from(`${STX}I love robots`))
assert.deepEqual(spy.getCall(1).args[0], Buffer.from(`${STX}Each and Every One`))
Expand All @@ -53,7 +53,7 @@ describe('StartEndParser', () => {
parser.write(Buffer.from(`${STX}I love robots${ETX}${STX}Each `))
parser.write(Buffer.from(`and Every One${ETX}`))
parser.write(Buffer.from(STX))
parser.write(Buffer.from(`even you!`))
parser.write(Buffer.from('even you!'))

assert.deepEqual(spy.getCall(0).args[0], Buffer.from(`I love robots${ETX}`))
assert.deepEqual(spy.getCall(1).args[0], Buffer.from(`Each and Every One${ETX}`))
Expand All @@ -72,7 +72,7 @@ describe('StartEndParser', () => {
parser.write(Buffer.from(`${STX}I love robots${ETX}${STX}Each `))
parser.write(Buffer.from(`and Every One${ETX}`))
parser.write(Buffer.from(STX))
parser.write(Buffer.from(`even you!`))
parser.write(Buffer.from('even you!'))

assert.deepEqual(spy.getCall(0).args[0], Buffer.from(`${STX}I love robots${ETX}`))
assert.deepEqual(spy.getCall(1).args[0], Buffer.from(`${STX}Each and Every One${ETX}`))
Expand Down Expand Up @@ -108,7 +108,7 @@ describe('StartEndParser', () => {
})
})

it(`throws when called with a 0 length startDelimiter`, () => {
it('throws when called with a 0 length startDelimiter', () => {
assert.throws(() => {
new StartEndParser({
startDelimiter: Buffer.alloc(0),
Expand All @@ -128,7 +128,7 @@ describe('StartEndParser', () => {
})
})

it(`throws when called with a 0 length endDelimiter`, () => {
it('throws when called with a 0 length endDelimiter', () => {
assert.throws(() => {
new StartEndParser({
endDelimiter: Buffer.alloc(0),
Expand All @@ -148,15 +148,15 @@ describe('StartEndParser', () => {
})
})

it(`allows setting of the startDelimiter and endDelimiter with strings`, () => {
it('allows setting of the startDelimiter and endDelimiter with strings', () => {
new StartEndParser({ startDelimiter: 'string', endDelimiter: 'string' })
})

it(`allows setting of the startDelimiter and endDelimiter with buffers`, () => {
it('allows setting of the startDelimiter and endDelimiter with buffers', () => {
new StartEndParser({ startDelimiter: Buffer.from([1]), endDelimiter: Buffer.from([1]) })
})

it(`allows setting of the startDelimiter and endDelimiter with arrays of bytes`, () => {
it('allows setting of the startDelimiter and endDelimiter with arrays of bytes', () => {
new StartEndParser({ startDelimiter: [1], endDelimiter: [1] })
})

Expand Down
2 changes: 1 addition & 1 deletion packages/parser-start-end/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ export class StartEndParser extends Transform {
if (startIndex >= 0 && endIndex >= 0) {
const block = data.slice(
startIndex + (this.includeStartDelimiter ? 0 : this.startDelimiter.length),
endIndex + (this.includeEndDelimiter ? this.endDelimiter.length : 0)
endIndex + (this.includeEndDelimiter ? this.endDelimiter.length : 0),
)

this.push(block)
Expand Down
Loading