Skip to content

Commit 8488dd1

Browse files
bbeckreconbot
authored andcommitted
add abilitiy for multiple delimitiers and multibyte delimiters to packet length parser
1 parent 929ebf8 commit 8488dd1

File tree

2 files changed

+60
-10
lines changed

2 files changed

+60
-10
lines changed

packages/parser-packet-length/lib/index.test.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,4 +90,45 @@ describe('DelimiterParser', () => {
9090
assert.deepEqual(spy.getCall(1).args[0], Buffer.concat([Buffer.from([0xaa, 0x02, 0x13, 0x00]), Buffer.from('Each and Every One\n')]))
9191
assert(spy.calledTwice)
9292
})
93+
94+
it('works with multiple delimiters', () => {
95+
const spy = sinon.spy()
96+
const parser = new PacketLengthParser({ delimiter: [0xaa, 0xbb], lengthOffset: 2, packetOverhead: 4, lengthBytes: 2 })
97+
parser.on('data', spy)
98+
parser.write(Buffer.from('\xbb\x01\x0d'))
99+
parser.write(Buffer.from('\x00I love hobits\xaa\x02\x13\x00Each '))
100+
parser.write(Buffer.from('and Every One\n'))
101+
102+
assert.deepEqual(spy.getCall(0).args[0], Buffer.concat([Buffer.from([0xbb, 0x01, 0x0d, 0x00]), Buffer.from('I love hobits')]))
103+
assert.deepEqual(spy.getCall(1).args[0], Buffer.concat([Buffer.from([0xaa, 0x02, 0x13, 0x00]), Buffer.from('Each and Every One\n')]))
104+
assert(spy.calledTwice)
105+
})
106+
107+
it('works with multibyte delimiters', () => {
108+
const spy = sinon.spy()
109+
const parser = new PacketLengthParser({ delimiter: [0xababba], delimiterBytes: 3, lengthOffset: 3, packetOverhead: 4, lengthBytes: 1 })
110+
parser.on('data', spy)
111+
parser.write(Buffer.from([0xab, 0xab, 0xba, 0x0d]))
112+
parser.write(Buffer.from('I love hobits'))
113+
parser.write(Buffer.from([0xab, 0xab, 0xba, 0x13]))
114+
parser.write(Buffer.from('Each and Every One\n'))
115+
116+
assert.deepEqual(spy.getCall(0).args[0], Buffer.concat([Buffer.from([0xab, 0xab, 0xba, 0x0d]), Buffer.from('I love hobits')]))
117+
assert.deepEqual(spy.getCall(1).args[0], Buffer.concat([Buffer.from([0xab, 0xab, 0xba, 0x13]), Buffer.from('Each and Every One\n')]))
118+
assert(spy.calledTwice)
119+
})
120+
121+
it('works with multiple multibyte delimiters', () => {
122+
const spy = sinon.spy()
123+
const parser = new PacketLengthParser({ delimiter: [0xababba, 0xbaddad], delimiterBytes: 3, lengthOffset: 3, packetOverhead: 4, lengthBytes: 1 })
124+
parser.on('data', spy)
125+
parser.write(Buffer.from([0xab, 0xab, 0xba, 0x0d]))
126+
parser.write(Buffer.from('I love hobits'))
127+
parser.write(Buffer.from([0xba, 0xdd, 0xad, 0x13]))
128+
parser.write(Buffer.from('Each and Every One\n'))
129+
130+
assert.deepEqual(spy.getCall(0).args[0], Buffer.concat([Buffer.from([0xab, 0xab, 0xba, 0x0d]), Buffer.from('I love hobits')]))
131+
assert.deepEqual(spy.getCall(1).args[0], Buffer.concat([Buffer.from([0xba, 0xdd, 0xad, 0x13]), Buffer.from('Each and Every One\n')]))
132+
assert(spy.calledTwice)
133+
})
93134
})

packages/parser-packet-length/lib/index.ts

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import { Transform, TransformCallback, TransformOptions } from 'stream'
22

33
export interface PacketLengthOptions extends TransformOptions {
4-
/** delimiter to use defaults to 0xaa */
5-
delimiter?: number
4+
/** delimiter(s) to use defaults to 0xaa */
5+
delimiter?: number | number[]
6+
/** delimiter length in bytes defaults to 1 */
7+
delimiterBytes?: number
68
/** overhead of packet (including length, delimiter and any checksum / packet footer) defaults to 2 */
79
packetOverhead?: number
810
/** number of bytes containing length defaults to 1 */
@@ -29,14 +31,15 @@ export interface PacketLengthOptions extends TransformOptions {
2931
export class PacketLengthParser extends Transform {
3032
buffer: Buffer
3133
start: boolean
32-
opts: { delimiter: number, packetOverhead: number, lengthBytes: number, lengthOffset: number, maxLen: number }
34+
opts: { delimiter: number[], delimiterBytes: number, packetOverhead: number, lengthBytes: number, lengthOffset: number, maxLen: number }
3335
constructor(options: PacketLengthOptions = {}) {
3436
super(options)
3537

36-
const { delimiter = 0xaa, packetOverhead = 2, lengthBytes = 1, lengthOffset = 1, maxLen = 0xff } = options
38+
const { delimiter = [0xaa], delimiterBytes = 1, packetOverhead = 2, lengthBytes = 1, lengthOffset = 1, maxLen = 0xff } = options
3739

3840
this.opts = {
39-
delimiter,
41+
delimiter: ([] as number[]).concat(delimiter),
42+
delimiterBytes,
4043
packetOverhead,
4144
lengthBytes,
4245
lengthOffset,
@@ -51,13 +54,8 @@ export class PacketLengthParser extends Transform {
5154
for (let ndx = 0; ndx < chunk.length; ndx++) {
5255
const byte = chunk[ndx]
5356

54-
if (byte === this.opts.delimiter) {
55-
this.start = true
56-
}
57-
5857
if (true === this.start) {
5958
this.buffer = Buffer.concat([this.buffer, Buffer.from([byte])])
60-
6159
if (this.buffer.length >= this.opts.lengthOffset + this.opts.lengthBytes) {
6260
const len = this.buffer.readUIntLE(this.opts.lengthOffset, this.opts.lengthBytes)
6361

@@ -67,6 +65,17 @@ export class PacketLengthParser extends Transform {
6765
this.start = false
6866
}
6967
}
68+
} else {
69+
this.buffer = Buffer.concat([Buffer.from([byte]), this.buffer])
70+
if (this.buffer.length === this.opts.delimiterBytes) {
71+
const delimiter = this.buffer.readUIntLE(0, this.opts.delimiterBytes)
72+
if (this.opts.delimiter.includes(delimiter)) {
73+
this.start = true
74+
this.buffer = Buffer.from([...this.buffer].reverse())
75+
} else {
76+
this.buffer = Buffer.from(this.buffer.subarray(1, this.buffer.length))
77+
}
78+
}
7079
}
7180
}
7281

0 commit comments

Comments
 (0)