Skip to content

Commit 2ddfcfd

Browse files
committed
do not use node buffer
1 parent a68371a commit 2ddfcfd

5 files changed

Lines changed: 175 additions & 133 deletions

File tree

‎README.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ Here are some non-exhaustive examples:
2020
```typescript
2121
import { Decoder } from "binary-util"
2222

23-
const data = Buffer.from([
23+
const data = new Uint8Array([
2424
0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x2c, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x21,
2525
])
2626
const decoder = new Decoder(data)

‎src/decoder.test.ts‎

Lines changed: 32 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
1-
import { Buffer } from "node:buffer"
2-
31
import { describe, expect, it } from "vitest"
42

53
// eslint-disable-next-line antfu/no-import-dist
64
import { Decoder } from "../dist/decoder.mjs"
75

86
describe(".currentOffset", () => {
97
it("example works as described", () => {
10-
const buffer = Buffer.from([0x01, 0x01, 0x00, 0x00])
8+
const buffer = new Uint8Array([0x01, 0x01, 0x00, 0x00])
119
const decoder = new Decoder(buffer)
1210
expect(decoder.readUint32()).toBe(257)
1311
expect(decoder.currentOffset).toBe(4)
@@ -16,7 +14,7 @@ describe(".currentOffset", () => {
1614

1715
describe(".endianness", () => {
1816
it("example works as described", () => {
19-
const buffer = Buffer.from([0x00, 0x00, 0x01, 0x01])
17+
const buffer = new Uint8Array([0x00, 0x00, 0x01, 0x01])
2018
const decoder = new Decoder(buffer)
2119
decoder.endianness("big")
2220
expect(decoder.readUint32()).toBe(257)
@@ -25,7 +23,7 @@ describe(".endianness", () => {
2523

2624
describe(".seek", () => {
2725
it("example works as described", () => {
28-
const buffer = Buffer.from([0xff, 0xff, 0x01, 0x00])
26+
const buffer = new Uint8Array([0xff, 0xff, 0x01, 0x00])
2927
const decoder = new Decoder(buffer)
3028
expect(decoder.seek(2)).toBe(0)
3129
expect(decoder.readUint16()).toBe(1)
@@ -34,7 +32,7 @@ describe(".seek", () => {
3432

3533
describe(".goto", () => {
3634
it("example works as described", () => {
37-
const buffer = Buffer.from([0xff, 0xff, 0x01, 0x00])
35+
const buffer = new Uint8Array([0xff, 0xff, 0x01, 0x00])
3836
const decoder = new Decoder(buffer)
3937
expect(decoder.readUint16()).toBe(65535)
4038
expect(decoder.goto(0)).toBe(2)
@@ -45,21 +43,21 @@ describe(".goto", () => {
4543

4644
describe(".alignTo", () => {
4745
it("skips forwards correctly if diff if positive", () => {
48-
const decoder = new Decoder(Buffer.alloc(16))
46+
const decoder = new Decoder(new Uint8Array(16))
4947
decoder.seek(12)
5048
decoder.alignTo(16)
5149
expect(decoder.currentOffset).toBe(16)
5250
})
5351

5452
it("skips forwards correctly if diff if negative", () => {
55-
const decoder = new Decoder(Buffer.alloc(16))
53+
const decoder = new Decoder(new Uint8Array(16))
5654
decoder.seek(4)
5755
decoder.alignTo(16)
5856
expect(decoder.currentOffset).toBe(16)
5957
})
6058

6159
it("does nothing if already aligned", () => {
62-
const decoder = new Decoder(Buffer.alloc(16))
60+
const decoder = new Decoder(new Uint8Array(16))
6361
decoder.seek(8)
6462
decoder.alignTo(4)
6563
expect(decoder.currentOffset).toBe(8)
@@ -68,7 +66,7 @@ describe(".alignTo", () => {
6866
it("example works as described", () => {
6967
// prettier-ignore
7068
// Assume we have a header 5 bytes long, then 3 bytes of padding up to 8 bytes in, then more data
71-
const buffer = Buffer.from([
69+
const buffer = new Uint8Array([
7270
0x74, 0xee, 0xb2, 0x36, 0x0c, 0x00, 0x00, 0x00,
7371
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
7472
])
@@ -85,13 +83,13 @@ describe(".alignTo", () => {
8583
describe("integers", () => {
8684
describe(".readInt8", () => {
8785
it("example works as described", () => {
88-
const decoder = new Decoder(Buffer.from([0xff]))
86+
const decoder = new Decoder(new Uint8Array([0xff]))
8987
expect(decoder.readInt8()).toBe(-1)
9088
})
9189

9290
it("pointer example works as described", () => {
93-
// (3 + 0) | pad | -1
94-
const decoder = new Decoder(Buffer.from([0x03, 0x00, 0x00, 0xff]))
91+
// (3 + 0) | pad | -1
92+
const decoder = new Decoder(new Uint8Array([0x03, 0x00, 0x00, 0xff]))
9593
const pointer = decoder.readUint16()
9694
expect(pointer).toBe(3)
9795
expect(decoder.readInt8({ pointer })).toBe(-1)
@@ -100,13 +98,13 @@ describe("integers", () => {
10098

10199
describe(".readUint8", () => {
102100
it("example works as described", () => {
103-
const decoder = new Decoder(Buffer.from([0xff]))
101+
const decoder = new Decoder(new Uint8Array([0xff]))
104102
expect(decoder.readUint8()).toBe(255)
105103
})
106104

107105
it("pointer example works as described", () => {
108-
// (3 + 0) | pad | -1
109-
const decoder = new Decoder(Buffer.from([0x03, 0x00, 0x00, 0xff]))
106+
// (3 + 0) | pad | -1
107+
const decoder = new Decoder(new Uint8Array([0x03, 0x00, 0x00, 0xff]))
110108
const pointer = decoder.readUint16()
111109
expect(pointer).toBe(3)
112110
expect(decoder.readUint8({ pointer })).toBe(255)
@@ -115,12 +113,12 @@ describe("integers", () => {
115113

116114
describe(".readInt16", () => {
117115
it("example works as described", () => {
118-
const decoder = new Decoder(Buffer.from([0xff, 0xff]))
116+
const decoder = new Decoder(new Uint8Array([0xff, 0xff]))
119117
expect(decoder.readInt16()).toBe(-1)
120118
})
121119

122120
it("pointer example works as described", () => {
123-
const decoder = new Decoder(Buffer.from([0x03, 0x00, 0x00, 0xff, 0xff]))
121+
const decoder = new Decoder(new Uint8Array([0x03, 0x00, 0x00, 0xff, 0xff]))
124122
const pointer = decoder.readUint16()
125123
expect(pointer).toBe(3)
126124
expect(decoder.readInt16({ pointer })).toBe(-1)
@@ -129,13 +127,13 @@ describe("integers", () => {
129127

130128
describe(".readUint16", () => {
131129
it("decodes a value correctly", () => {
132-
const decoder = new Decoder(Buffer.from([0xff, 0xff]))
130+
const decoder = new Decoder(new Uint8Array([0xff, 0xff]))
133131
expect(decoder.readUint16()).toBe(65535)
134132
})
135133

136134
it("decodes a value via a pointer correctly", () => {
137-
// (3 + 0) | pad | -1
138-
const decoder = new Decoder(Buffer.from([0x03, 0x00, 0x00, 0xff, 0xff]))
135+
// (3 + 0) | pad | -1
136+
const decoder = new Decoder(new Uint8Array([0x03, 0x00, 0x00, 0xff, 0xff]))
139137
const pointer = decoder.readUint16()
140138
expect(pointer).toBe(3)
141139
expect(decoder.readUint16({ pointer })).toBe(65535)
@@ -146,32 +144,32 @@ describe("integers", () => {
146144
describe(".readBuffer", () => {
147145
it("returns part of buffer", () => {
148146
const decoder = new Decoder(
149-
Buffer.from([0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]),
147+
new Uint8Array([0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]),
150148
)
151-
expect(decoder.readBuffer({ length: 2 })).toEqual(Buffer.from([0x01, 0x02]))
149+
expect(decoder.readBuffer({ length: 2 })).toEqual(new Uint8Array([0x01, 0x02]))
152150
})
153151

154152
it("uses currentOffset", () => {
155153
const decoder = new Decoder(
156-
Buffer.from([0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]),
154+
new Uint8Array([0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]),
157155
)
158156
decoder.seek(2)
159-
expect(decoder.readBuffer({ length: 2 })).toEqual(Buffer.from([0x03, 0x04]))
157+
expect(decoder.readBuffer({ length: 2 })).toEqual(new Uint8Array([0x03, 0x04]))
160158
})
161159

162160
it("pointer option works", () => {
163161
const decoder = new Decoder(
164-
Buffer.from([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x09]),
162+
new Uint8Array([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x09]),
165163
)
166164
expect(decoder.readBuffer({ pointer: 0x06, length: 2 })).toEqual(
167-
Buffer.from([0x08, 0x09]),
165+
new Uint8Array([0x08, 0x09]),
168166
)
169167
})
170168
})
171169

172170
describe(".readString", () => {
173171
it("should parse strings correctly", () => {
174-
const data = Buffer.from("testhelloworld")
172+
const data = new TextEncoder().encode("testhelloworld")
175173

176174
const decoder = new Decoder(data)
177175
expect(decoder.readString({ length: 4 })).toBe("test")
@@ -180,7 +178,7 @@ describe(".readString", () => {
180178
})
181179

182180
it("should parse zeroed strings correctly", () => {
183-
const data = Buffer.from("test\x00hello\x00world\x00")
181+
const data = new TextEncoder().encode("test\x00hello\x00world\x00")
184182

185183
const decoder = new Decoder(data)
186184
expect(decoder.readString({ zeroed: true })).toBe("test")
@@ -190,7 +188,7 @@ describe(".readString", () => {
190188
})
191189

192190
it("should parse the README example", () => {
193-
const data = Buffer.from([
191+
const data = new Uint8Array([
194192
0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x2c, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x21,
195193
])
196194
const decoder = new Decoder(data)
@@ -200,7 +198,9 @@ it("should parse the README example", () => {
200198
expect(decoder.readString({ length: 7 })).toBe(", World")
201199

202200
// Or you can use it more ergonomically when possible
203-
const decoder2 = new Decoder(Buffer.alloc(2, 2))
201+
const filledArray = new Uint8Array(2)
202+
filledArray.fill(2)
203+
const decoder2 = new Decoder(filledArray)
204204
const result = {
205205
a: decoder2.readUint8(),
206206
b: decoder2.readUint8(),
@@ -210,7 +210,7 @@ it("should parse the README example", () => {
210210
})
211211

212212
it("should allow parsing simple data", () => {
213-
const testBuffer = Buffer.alloc(17)
213+
const testBuffer = new Uint8Array(17)
214214
const values = [3257, 3263, 6483, 9773]
215215
const view = new DataView(testBuffer.buffer)
216216
view.setInt8(0, 4)

‎src/decoder.ts‎

Lines changed: 27 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
1-
import type { Buffer } from "node:buffer"
1+
import { TextDecoder } from "node:util"
22

33
type BaseOptions = {
44
pointer?: number
55
}
66

77
type BaseStringOptions = {
8-
encoding?: BufferEncoding
8+
encoding?: "utf8"
99
}
1010

1111
type BufferOptions = BaseOptions & { length: number }
1212

1313
type StringOptions = BaseStringOptions & ({ length: number } | { zeroed: boolean })
1414

1515
export class Decoder {
16-
#buffer: Buffer
16+
#buffer: Uint8Array
1717
#currentOffset = 0
1818
#littleEndian = true
1919

@@ -23,7 +23,7 @@ export class Decoder {
2323
*
2424
* Defaults to little endian.
2525
*/
26-
constructor(buffer: Buffer) {
26+
constructor(buffer: Uint8Array) {
2727
this.#buffer = buffer
2828
}
2929

@@ -32,8 +32,8 @@ export class Decoder {
3232
*
3333
* @example
3434
* ```ts
35-
* // 1 + 256 + 0 + 0
36-
* const buffer = Buffer.from([0x01, 0x01, 0x00, 0x00])
35+
* // 1 + 256 + 0 + 0
36+
* const buffer = new Uint8Array([0x01, 0x01, 0x00, 0x00])
3737
* const decoder = new Decoder(buffer)
3838
* decoder.readUint32() // 257
3939
* decoder.currentOffset // 4
@@ -48,8 +48,8 @@ export class Decoder {
4848
* @param endianness - `big` or `little`
4949
* @example
5050
* ```ts
51-
* // 0 + 0 + 256 + 1
52-
* const buffer = Buffer.from([0x00, 0x00, 0x01, 0x01])
51+
* // 0 + 0 + 256 + 1
52+
* const buffer = new Uint8Array([0x00, 0x00, 0x01, 0x01])
5353
* const decoder = new Decoder(buffer)
5454
* decoder.endianness("big")
5555
* decoder.readUint32() // 257
@@ -65,8 +65,8 @@ export class Decoder {
6565
* @returns The previous offset.
6666
* @example
6767
* ```ts
68-
* // (max + max)|(1 + 0)
69-
* const buffer = Buffer.from([0xFF, 0xFF, 0x01, 0x00])
68+
* // (max + max)|(1 + 0)
69+
* const buffer = new Uint8Array([0xFF, 0xFF, 0x01, 0x00])
7070
* const decoder = new Decoder(buffer)
7171
* decoder.seek(2) // 0
7272
* decoder.readUint16() // 1
@@ -84,8 +84,8 @@ export class Decoder {
8484
* @returns The previous offset.
8585
* @example
8686
* ```ts
87-
* // (max + max)|(1 + 0)
88-
* const buffer = Buffer.from([0xff, 0xff, 0x01, 0x00])
87+
* // (max + max)|(1 + 0)
88+
* const buffer = new Uint8Array([0xff, 0xff, 0x01, 0x00])
8989
* const decoder = new Decoder(buffer)
9090
* decoder.readUint16() // 65535
9191
* decoder.goto(0) // 2
@@ -109,7 +109,7 @@ export class Decoder {
109109
* @example
110110
* ```ts
111111
* // Assume we have a header 5 bytes long, then 3 bytes of padding up to 8 bytes in, then more data
112-
* const buffer = Buffer.from([
112+
* const buffer = new Uint8Array([
113113
* 0x74, 0xee, 0xb2, 0x36, 0x0c, 0x00, 0x00, 0x00,
114114
* 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
115115
* ])
@@ -142,13 +142,13 @@ export class Decoder {
142142
* @returns Value between -128 and 127.
143143
* @example
144144
* ```ts
145-
* const decoder = new Decoder(Buffer.from([0xff]))
145+
* const decoder = new Decoder(new Uint8Array([0xff]))
146146
* expect(decoder.readInt8()).toBe(-1)
147147
* ```
148148
* @example Read via pointer offset
149149
* ```ts
150-
* // (3 + 0) | pad | -1
151-
* const decoder = new Decoder(Buffer.from([0x03, 0x00, 0x00, 0xff]))
150+
* // (3 + 0) | pad | -1
151+
* const decoder = new Decoder(new Uint8Array([0x03, 0x00, 0x00, 0xff]))
152152
* const pointer = decoder.readUint16() // 3
153153
* decoder.readInt8({ pointer }) // -1
154154
* ```
@@ -174,13 +174,13 @@ export class Decoder {
174174
* @returns Value between 0 and 255.
175175
* @example
176176
* ```ts
177-
* const decoder = new Decoder(Buffer.from([0xff]))
177+
* const decoder = new Decoder(new Uint8Array([0xff]))
178178
* expect(decoder.readInt8()).toBe(255)
179179
* ```
180180
* @example Read via pointer offset
181181
* ```ts
182-
* // (3 + 0) | pad | -1
183-
* const decoder = new Decoder(Buffer.from([0x03, 0x00, 0x00, 0xff]))
182+
* // (3 + 0) | pad | -1
183+
* const decoder = new Decoder(new Uint8Array([0x03, 0x00, 0x00, 0xff]))
184184
* const pointer = decoder.readUint16() // 3
185185
* decoder.readInt8({ pointer }) // 255
186186
* ```
@@ -377,7 +377,7 @@ export class Decoder {
377377
* @param opts.length {number} - Length of slice (not inclusive).
378378
* @param opts.pointer {number} - See {@link Decoder#readUint8}.
379379
*/
380-
readBuffer(opts: BufferOptions): Buffer {
380+
readBuffer(opts: BufferOptions): Uint8Array {
381381
const offset = opts.pointer ?? this.#currentOffset
382382
const result = this.#buffer.subarray(offset, offset + opts.length)
383383

@@ -396,17 +396,17 @@ export class Decoder {
396396
* @param opts.encoding - Defaults to `utf8`.
397397
* @example Zeroed
398398
* ```ts
399-
* const decoder = new Decoder(Buffer.from([0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x00]))
399+
* const decoder = new Decoder(new Uint8Array([0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x00]))
400400
* decoder.readString({ zeroed: true }) // "hello"
401401
* ```
402402
* @example Length
403403
* ```ts
404-
* const decoder = new Decoder(Buffer.from([0x68, 0x65, 0x6c, 0x6c, 0x6f]))
404+
* const decoder = new Decoder(new Uint8Array([0x68, 0x65, 0x6c, 0x6c, 0x6f]))
405405
* decoder.readString({ length: 5 }) // "hello"
406406
* ```
407407
*/
408408
readString(opts: StringOptions): string {
409-
let strBuffer: Buffer | null = null
409+
let strBuffer: Uint8Array | null = null
410410

411411
if ("length" in opts && opts.length != null) {
412412
strBuffer = this.readBuffer(opts)
@@ -431,6 +431,9 @@ export class Decoder {
431431
throw new Error("You need to specify either `zeroed` or `length`.")
432432
}
433433

434-
return strBuffer.toString(opts.encoding ?? "utf8")
434+
this.#textDecoder ??= new TextDecoder(opts.encoding ?? "utf8")
435+
return this.#textDecoder.decode(strBuffer)
435436
}
437+
438+
#textDecoder!: TextDecoder
436439
}

0 commit comments

Comments
 (0)