strtok3 10.3.5 → 10.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.txt +21 -21
- package/README.md +561 -399
- package/lib/AbortSignal.d.ts +2 -0
- package/lib/AbortSignal.js +7 -0
- package/lib/AbstractTokenizer.d.ts +40 -2
- package/lib/AbstractTokenizer.js +101 -16
- package/lib/BlobTokenizer.d.ts +1 -1
- package/lib/BlobTokenizer.js +14 -11
- package/lib/BufferSizeError.d.ts +19 -0
- package/lib/BufferSizeError.js +27 -0
- package/lib/BufferTokenizer.d.ts +1 -1
- package/lib/BufferTokenizer.js +6 -8
- package/lib/FileTokenizer.d.ts +4 -3
- package/lib/FileTokenizer.js +22 -6
- package/lib/ReadStreamTokenizer.js +26 -8
- package/lib/core.d.ts +7 -6
- package/lib/core.js +11 -4
- package/lib/index.d.ts +4 -4
- package/lib/index.js +2 -2
- package/lib/stream/AbstractStreamReader.js +5 -3
- package/lib/stream/Errors.js +3 -3
- package/lib/stream/StreamReader.d.ts +4 -3
- package/lib/stream/StreamReader.js +40 -24
- package/lib/stream/WebStreamByobReader.js +5 -3
- package/lib/stream/WebStreamDefaultReader.d.ts +1 -1
- package/lib/stream/WebStreamDefaultReader.js +9 -4
- package/lib/stream/WebStreamReader.d.ts +1 -1
- package/lib/stream/WebStreamReader.js +1 -1
- package/lib/stream/WebStreamReaderFactory.js +1 -1
- package/lib/stream/index.d.ts +1 -1
- package/lib/types.d.ts +7 -0
- package/package.json +95 -94
package/README.md
CHANGED
|
@@ -1,399 +1,561 @@
|
|
|
1
|
-
[](https://github.com/Borewit/strtok3/actions/workflows/ci.yml)
|
|
2
|
-
[](https://github.com/Borewit/strtok3/actions/workflows/codeql.yml)
|
|
3
|
-
[](https://npmjs.org/package/strtok3)
|
|
4
|
-
[](https://npmcharts.com/compare/strtok3,token-types?start=1200&interval=30)
|
|
5
|
-
[](https://deepscan.io/dashboard#view=project&tid=5165&pid=8526&bid=103329)
|
|
6
|
-
[](https://snyk.io/test/github/Borewit/strtok3?targetFile=package.json)
|
|
7
|
-
[](https://www.codacy.com/app/Borewit/strtok3?utm_source=github.com&utm_medium=referral&utm_content=Borewit/strtok3&utm_campaign=Badge_Grade)
|
|
8
|
-
# strtok3
|
|
9
|
-
|
|
10
|
-
A promise
|
|
11
|
-
|
|
12
|
-
The `strtok3` module provides several methods for creating a [*tokenizer*](#tokenizer-object) from various input sources.
|
|
13
|
-
Designed for:
|
|
14
|
-
* Seamless support in streaming environments.
|
|
15
|
-
* Efficiently decode binary data, strings, and numbers.
|
|
16
|
-
* Reading [predefined](https://github.com/Borewit/token-types) or custom tokens.
|
|
17
|
-
* Offering [*tokenizers*](#tokenizer-object) for reading from [files](#
|
|
18
|
-
|
|
19
|
-
### Features
|
|
20
|
-
`strtok3` can read from:
|
|
21
|
-
* Files, using a file path as input.
|
|
22
|
-
* Node.js [streams](https://nodejs.org/api/stream.html).
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
* [
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
```
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
parse()
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
```
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
1
|
+
[](https://github.com/Borewit/strtok3/actions/workflows/ci.yml)
|
|
2
|
+
[](https://github.com/Borewit/strtok3/actions/workflows/codeql.yml)
|
|
3
|
+
[](https://npmjs.org/package/strtok3)
|
|
4
|
+
[](https://npmcharts.com/compare/strtok3,token-types?start=1200&interval=30)
|
|
5
|
+
[](https://deepscan.io/dashboard#view=project&tid=5165&pid=8526&bid=103329)
|
|
6
|
+
[](https://snyk.io/test/github/Borewit/strtok3?targetFile=package.json)
|
|
7
|
+
[](https://www.codacy.com/app/Borewit/strtok3?utm_source=github.com&utm_medium=referral&utm_content=Borewit/strtok3&utm_campaign=Badge_Grade)
|
|
8
|
+
# strtok3
|
|
9
|
+
|
|
10
|
+
A promise-based streaming [*tokenizer*](#tokenizer-object) for [Node.js](https://nodejs.org) and browsers.
|
|
11
|
+
|
|
12
|
+
The `strtok3` module provides several methods for creating a [*tokenizer*](#tokenizer-object) from various input sources.
|
|
13
|
+
Designed for:
|
|
14
|
+
* Seamless support in streaming environments.
|
|
15
|
+
* Efficiently decode binary data, strings, and numbers.
|
|
16
|
+
* Reading [predefined](https://github.com/Borewit/token-types) or custom tokens.
|
|
17
|
+
* Offering [*tokenizers*](#tokenizer-object) for reading from [files](#fromfile-function), [streams](#fromstream-function) or [Uint8Arrays](#frombuffer-function).
|
|
18
|
+
|
|
19
|
+
### Features
|
|
20
|
+
`strtok3` can read from:
|
|
21
|
+
* Files, using a file path as input.
|
|
22
|
+
* Node.js [streams](https://nodejs.org/api/stream.html).
|
|
23
|
+
* WHATWG [ReadableStream](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream) objects containing `Uint8Array` chunks.
|
|
24
|
+
* [Buffer](https://nodejs.org/api/buffer.html) or [Uint8Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array).
|
|
25
|
+
* [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) or [File](https://developer.mozilla.org/en-US/docs/Web/API/File) objects.
|
|
26
|
+
* HTTP chunked transfer provided by [@tokenizer/http](https://github.com/Borewit/tokenizer-http).
|
|
27
|
+
* [Amazon S3](https://aws.amazon.com/s3) chunks with [@tokenizer/s3](https://github.com/Borewit/tokenizer-s3).
|
|
28
|
+
|
|
29
|
+
## Installation
|
|
30
|
+
|
|
31
|
+
```sh
|
|
32
|
+
npm install strtok3
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Compatibility
|
|
36
|
+
|
|
37
|
+
Starting with version 7, the module has migrated from [CommonJS](https://en.wikipedia.org/wiki/CommonJS) to [pure ECMAScript Module (ESM)](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c).
|
|
38
|
+
The distributed JavaScript codebase is compliant with the [ECMAScript 2020 (11th Edition)](https://en.wikipedia.org/wiki/ECMAScript_version_history#11th_Edition_%E2%80%93_ECMAScript_2020) standard.
|
|
39
|
+
|
|
40
|
+
Requires a modern browser, Node.js (V8) ≥ 18 engine or Bun (JavaScriptCore) ≥ 1.2.
|
|
41
|
+
It can also be used in a browser environment when bundled with a module bundler.
|
|
42
|
+
|
|
43
|
+
For TypeScript CommonJS backward compatibility, you can use [load-esm](https://github.com/Borewit/load-esm).
|
|
44
|
+
|
|
45
|
+
Use Node.js 24 LTS to build the project and install development dependencies.
|
|
46
|
+
This build requirement is separate from the Node.js ≥ 18 runtime requirement in `package.json`.
|
|
47
|
+
CI builds once with Node.js 24, then runs the compiled JavaScript unit tests across the Node.js compatibility matrix and Bun 1.2.x, 1.3.x, and 1.4.x.
|
|
48
|
+
Coverage is collected in a separate Node.js 24 job.
|
|
49
|
+
|
|
50
|
+
For local development, running the TypeScript tests with `tsx` requires Node.js 18.19+ (18.x) or Node.js ≥ 20.6.0.
|
|
51
|
+
|
|
52
|
+
## Support the Project
|
|
53
|
+
If you find this project useful and would like to support its development, consider sponsoring or contributing:
|
|
54
|
+
|
|
55
|
+
- [Become a sponsor to Borewit](https://github.com/sponsors/Borewit)
|
|
56
|
+
|
|
57
|
+
- Buy me a coffee:
|
|
58
|
+
|
|
59
|
+
<a href="https://www.buymeacoffee.com/borewit" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/default-orange.png" alt="Buy me A coffee" height="41" width="174"></a>
|
|
60
|
+
|
|
61
|
+
## API Documentation
|
|
62
|
+
|
|
63
|
+
### strtok3 methods
|
|
64
|
+
|
|
65
|
+
Use one of the methods to instantiate an [*abstract tokenizer*](#tokenizer-object):
|
|
66
|
+
- [fromBlob](#fromblob-function)
|
|
67
|
+
- [fromBuffer](#frombuffer-function)
|
|
68
|
+
- [fromFile](#fromfile-function)*
|
|
69
|
+
- [fromStream](#fromstream-function)*
|
|
70
|
+
- [fromWebStream](#fromwebstream-function)
|
|
71
|
+
|
|
72
|
+
> [!NOTE]
|
|
73
|
+
> `fromFile` requires Node.js file-system APIs, and `fromStream` requires a Node.js readable stream.
|
|
74
|
+
> In browsers, use `fromBlob`, `fromBuffer`, or `fromWebStream`.
|
|
75
|
+
|
|
76
|
+
All methods return a [`Tokenizer`](#tokenizer-object), either directly or via a promise.
|
|
77
|
+
|
|
78
|
+
#### `fromBlob()` function
|
|
79
|
+
|
|
80
|
+
Create a tokenizer from a [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob).
|
|
81
|
+
|
|
82
|
+
```ts
|
|
83
|
+
function fromBlob(blob: Blob, options?: ITokenizerOptions): BlobTokenizer
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
| Parameter | Optional | Type | Description |
|
|
87
|
+
|-----------|-----------|---------------------------------------------------|----------------------------------------------------------------------------------------|
|
|
88
|
+
| blob | no | [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) | [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) or [File](https://developer.mozilla.org/en-US/docs/Web/API/File) to read from |
|
|
89
|
+
| options | yes | [ITokenizerOptions](#itokenizeroptions-interface) | Tokenizer options |
|
|
90
|
+
|
|
91
|
+
Returns a [*tokenizer*](#tokenizer-object).
|
|
92
|
+
|
|
93
|
+
```js
|
|
94
|
+
import { fromBlob } from 'strtok3';
|
|
95
|
+
import * as Token from 'token-types';
|
|
96
|
+
|
|
97
|
+
async function parse() {
|
|
98
|
+
const blob = new Blob([new Uint8Array([42])]);
|
|
99
|
+
|
|
100
|
+
const tokenizer = fromBlob(blob);
|
|
101
|
+
|
|
102
|
+
const myUint8Number = await tokenizer.readToken(Token.UINT8);
|
|
103
|
+
console.log(`My number: ${myUint8Number}`);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
parse();
|
|
107
|
+
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
#### `fromBuffer()` function
|
|
111
|
+
|
|
112
|
+
Create a tokenizer from memory ([Uint8Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array) or Node.js [Buffer](https://nodejs.org/api/buffer.html)).
|
|
113
|
+
|
|
114
|
+
```ts
|
|
115
|
+
function fromBuffer(uint8Array: Uint8Array, options?: ITokenizerOptions): BufferTokenizer
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
| Parameter | Optional | Type | Description |
|
|
119
|
+
|------------|----------|--------------------------------------------------|-----------------------------------|
|
|
120
|
+
| uint8Array | no | [Uint8Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array) | Buffer or Uint8Array to read from |
|
|
121
|
+
| options | yes | [ITokenizerOptions](#itokenizeroptions-interface) | Tokenizer options |
|
|
122
|
+
|
|
123
|
+
Returns a [*tokenizer*](#tokenizer-object).
|
|
124
|
+
|
|
125
|
+
```js
|
|
126
|
+
import { fromBuffer } from 'strtok3';
|
|
127
|
+
import * as Token from 'token-types';
|
|
128
|
+
|
|
129
|
+
const tokenizer = fromBuffer(new Uint8Array([42]));
|
|
130
|
+
|
|
131
|
+
async function parse() {
|
|
132
|
+
const myUint8Number = await tokenizer.readToken(Token.UINT8);
|
|
133
|
+
console.log(`My number: ${myUint8Number}`);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
parse();
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
#### `fromFile` function
|
|
140
|
+
|
|
141
|
+
Creates a [*tokenizer*](#tokenizer-object) from a local file.
|
|
142
|
+
|
|
143
|
+
```ts
|
|
144
|
+
function fromFile(sourceFilePath: string, options?: ITokenizerOptions): Promise<FileTokenizer>
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
| Parameter | Type | Description |
|
|
148
|
+
|----------------|----------|----------------------------|
|
|
149
|
+
| sourceFilePath | `string` | Path to file to read from |
|
|
150
|
+
| options | [ITokenizerOptions](#itokenizeroptions-interface) | Optional tokenizer options |
|
|
151
|
+
|
|
152
|
+
> [!NOTE]
|
|
153
|
+
> - Only available for Node.js engines
|
|
154
|
+
> - `fromFile` automatically embeds [file information](#ifileinfo-interface)
|
|
155
|
+
|
|
156
|
+
A Promise resolving to a [*tokenizer*](#tokenizer-object) which can be used to parse a file.
|
|
157
|
+
|
|
158
|
+
```js
|
|
159
|
+
import { fromFile } from 'strtok3';
|
|
160
|
+
import * as Token from 'token-types';
|
|
161
|
+
|
|
162
|
+
async function parse() {
|
|
163
|
+
const tokenizer = await fromFile('somefile.bin');
|
|
164
|
+
try {
|
|
165
|
+
const myNumber = await tokenizer.readToken(Token.UINT8);
|
|
166
|
+
console.log(`My number: ${myNumber}`);
|
|
167
|
+
} finally {
|
|
168
|
+
await tokenizer.close(); // Close the file
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
parse();
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
#### `fromStream()` function
|
|
178
|
+
|
|
179
|
+
Create a tokenizer from a Node.js [readable stream](https://nodejs.org/api/stream.html#readable-streams) containing binary data.
|
|
180
|
+
|
|
181
|
+
```ts
|
|
182
|
+
function fromStream(stream: Readable, options?: ITokenizerOptions): Promise<ReadStreamTokenizer>
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
| Parameter | Optional | Type | Description |
|
|
186
|
+
|-----------|----------|------|-------------|
|
|
187
|
+
| stream | no | Readable | Node.js readable stream to read from |
|
|
188
|
+
| options | yes | [ITokenizerOptions](#itokenizeroptions-interface) | Tokenizer options |
|
|
189
|
+
|
|
190
|
+
When importing from `strtok3` in Node.js, returns a promise resolving to a [*tokenizer*](#tokenizer-object).
|
|
191
|
+
For streams created by `createReadStream`, the file path and size are added to `tokenizer.fileInfo`.
|
|
192
|
+
The `strtok3/core` entry point also exports `fromStream`, but returns the tokenizer synchronously without looking up file information.
|
|
193
|
+
|
|
194
|
+
```js
|
|
195
|
+
import { createReadStream } from 'node:fs';
|
|
196
|
+
import { fromStream } from 'strtok3';
|
|
197
|
+
import * as Token from 'token-types';
|
|
198
|
+
|
|
199
|
+
async function parse() {
|
|
200
|
+
const stream = createReadStream('somefile.bin');
|
|
201
|
+
try {
|
|
202
|
+
const tokenizer = await fromStream(stream);
|
|
203
|
+
try {
|
|
204
|
+
const myNumber = await tokenizer.readToken(Token.UINT8);
|
|
205
|
+
console.log(`My number: ${myNumber}`);
|
|
206
|
+
} finally {
|
|
207
|
+
await tokenizer.close();
|
|
208
|
+
}
|
|
209
|
+
} finally {
|
|
210
|
+
stream.destroy();
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
parse();
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
#### `fromWebStream()` function
|
|
218
|
+
|
|
219
|
+
Create a tokenizer from a [WHATWG ReadableStream](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream) containing `Uint8Array` chunks.
|
|
220
|
+
|
|
221
|
+
Uses a BYOB reader when supported by the stream, otherwise a default reader. Source cleanup differs between these readers; see [`close()`](#close-function) and [`abort()`](#abort-function).
|
|
222
|
+
|
|
223
|
+
```ts
|
|
224
|
+
function fromWebStream(webStream: AnyWebByteStream, options?: ITokenizerOptions): ReadStreamTokenizer
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
| Parameter | Optional | Type | Description |
|
|
228
|
+
|----------------|----------|--------------------------------------------------------------------------|------------------------------------|
|
|
229
|
+
| webStream | no | [ReadableStream](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream) | WHATWG ReadableStream to read from |
|
|
230
|
+
| options | yes | [ITokenizerOptions](#itokenizeroptions-interface) | Tokenizer options |
|
|
231
|
+
|
|
232
|
+
Returns a [*tokenizer*](#tokenizer-object).
|
|
233
|
+
|
|
234
|
+
```js
|
|
235
|
+
import { fromWebStream } from 'strtok3';
|
|
236
|
+
import * as Token from 'token-types';
|
|
237
|
+
|
|
238
|
+
async function parse() {
|
|
239
|
+
const tokenizer = fromWebStream(readableStream);
|
|
240
|
+
try {
|
|
241
|
+
const myUint8Number = await tokenizer.readToken(Token.UINT8);
|
|
242
|
+
console.log(`My number: ${myUint8Number}`);
|
|
243
|
+
} finally {
|
|
244
|
+
await tokenizer.close();
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
parse();
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
### `Tokenizer` object
|
|
252
|
+
The *tokenizer* is an abstraction of a [stream](https://nodejs.org/api/stream.html), file or [Uint8Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array), allowing _reading_ or _peeking_ from the stream.
|
|
253
|
+
It can also be translated in chunked reads, as done in [@tokenizer/http](https://github.com/Borewit/tokenizer-http);
|
|
254
|
+
|
|
255
|
+
#### Key Features:
|
|
256
|
+
|
|
257
|
+
- Supports seeking within the stream using `tokenizer.ignore()`.
|
|
258
|
+
- Offers `peek` methods to preview data without advancing the read pointer.
|
|
259
|
+
- Maintains the read position via `tokenizer.position`.
|
|
260
|
+
- Supports random access for buffer, blob, and file tokenizers.
|
|
261
|
+
|
|
262
|
+
#### Tokenizer functions
|
|
263
|
+
|
|
264
|
+
_Read_ methods advance the stream pointer, while _peek_ methods do not.
|
|
265
|
+
|
|
266
|
+
There are two kinds of functions:
|
|
267
|
+
1. *read* methods: used to read a *token* or bytes into a buffer from the [*tokenizer*](#tokenizer-object). The position of the *tokenizer-stream* will advance with the number of bytes read.
|
|
268
|
+
2. *peek* methods: same as the read, but it will *not* advance the pointer. It allows to read (peek) ahead.
|
|
269
|
+
|
|
270
|
+
#### `readBuffer` function
|
|
271
|
+
|
|
272
|
+
Read data from the _tokenizer_ into provided "buffer" (`Uint8Array`).
|
|
273
|
+
`readBuffer(buffer, options?)`
|
|
274
|
+
|
|
275
|
+
```ts
|
|
276
|
+
readBuffer(buffer: Uint8Array, options?: IReadChunkOptions): Promise<number>;
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
| Parameter | Type | Description |
|
|
280
|
+
|------------|----------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|
281
|
+
| buffer | [Buffer](https://nodejs.org/api/buffer.html) | Uint8Array | Target buffer to write the data read to |
|
|
282
|
+
| options | [IReadChunkOptions](#ireadchunkoptions-interface) | Optional settings for the length, position, and handling of partial reads |
|
|
283
|
+
|
|
284
|
+
Return promise with number of bytes read.
|
|
285
|
+
The number of bytes read may be less than requested if the `mayBeLess` flag is set.
|
|
286
|
+
|
|
287
|
+
#### `peekBuffer` function
|
|
288
|
+
|
|
289
|
+
Peek (read ahead), from [*tokenizer*](#tokenizer-object), into the buffer without advancing the stream pointer.
|
|
290
|
+
|
|
291
|
+
```ts
|
|
292
|
+
peekBuffer(uint8Array: Uint8Array, options?: IReadChunkOptions): Promise<number>;
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
| Parameter | Type | Description |
|
|
296
|
+
|------------|-----------------------------------------|-----------------------------------------------------|
|
|
297
|
+
| buffer | Buffer | Uint8Array | Target buffer to write the data read (peeked) to. |
|
|
298
|
+
| options | [IReadChunkOptions](#ireadchunkoptions-interface) | Optional settings for the length, position, and handling of partial reads |
|
|
299
|
+
|
|
300
|
+
Return value `Promise<number>` Promise with number of bytes read. The number of bytes read may be less if the `mayBeLess` flag was set.
|
|
301
|
+
|
|
302
|
+
#### `readToken` function
|
|
303
|
+
|
|
304
|
+
Read a *token* from the tokenizer-stream.
|
|
305
|
+
|
|
306
|
+
```ts
|
|
307
|
+
readToken<Value>(token: IGetToken<Value>, position: number = this.position): Promise<Value>
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
| Parameter | Type | Description |
|
|
311
|
+
|------------|-------------------------|---------------------------------------------------------------------------------------------------------------------- |
|
|
312
|
+
| token | [IGetToken](#token-object) | Token to read from the tokenizer-stream. |
|
|
313
|
+
| position? | number | Offset where to begin reading. Defaults to `tokenizer.position` when omitted. |
|
|
314
|
+
|
|
315
|
+
Returns a `Promise<Value>` resolving to the decoded token value. Rejects with `EndOfStreamError` if fewer than `token.len` bytes are available.
|
|
316
|
+
|
|
317
|
+
#### `peekToken` function
|
|
318
|
+
|
|
319
|
+
Peek a *token* from the [*tokenizer*](#tokenizer-object).
|
|
320
|
+
|
|
321
|
+
```ts
|
|
322
|
+
peekToken<Value>(token: IGetToken<Value>, position: number | null = this.position): Promise<Value>
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
| Parameter | Type | Description |
|
|
326
|
+
|------------|----------------------------|-------------------------------------------------------------------------------------------------------------------------|
|
|
327
|
+
| token | [IGetToken](#token-object) | Token to peek from the tokenizer-stream. |
|
|
328
|
+
| position? | number | null | Offset where to begin peeking. Defaults to `tokenizer.position` when omitted or `null`. |
|
|
329
|
+
|
|
330
|
+
Return a promise with the token value peeked from the [*tokenizer*](#tokenizer-object).
|
|
331
|
+
|
|
332
|
+
#### `readNumber` function
|
|
333
|
+
|
|
334
|
+
Read a numeric [*token*](#token-object) from the [*tokenizer*](#tokenizer-object).
|
|
335
|
+
|
|
336
|
+
```ts
|
|
337
|
+
readNumber(token: IToken<number>): Promise<number>
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
| Parameter | Type | Description |
|
|
341
|
+
|------------|---------------------------------|----------------------------------------------------|
|
|
342
|
+
| token | [IToken<number>](#token-object) | Numeric token to read from the tokenizer-stream. |
|
|
343
|
+
|
|
344
|
+
A promise resolving to a numeric value read and decoded from the *tokenizer-stream*.
|
|
345
|
+
|
|
346
|
+
#### `peekNumber` function
|
|
347
|
+
|
|
348
|
+
Peek a numeric [*token*](#token-object) without advancing `tokenizer.position`.
|
|
349
|
+
|
|
350
|
+
```ts
|
|
351
|
+
peekNumber(token: IToken<number>): Promise<number>
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
Returns a promise resolving to the decoded numeric value.
|
|
355
|
+
Like `readNumber`, rejects with `EndOfStreamError` if the token cannot be read in full.
|
|
356
|
+
|
|
357
|
+
#### `ignore` function
|
|
358
|
+
|
|
359
|
+
Advance the offset pointer with the token number of bytes provided.
|
|
360
|
+
|
|
361
|
+
```ts
|
|
362
|
+
ignore(length: number): Promise<number>
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
| Parameter | Type | Description |
|
|
366
|
+
|------------|--------|------------------------------------------------------------------|
|
|
367
|
+
| length | number | Non-negative number of bytes to ignore. Advances `tokenizer.position`. |
|
|
368
|
+
|
|
369
|
+
Returns a promise resolving to the number of bytes ignored.
|
|
370
|
+
Buffer, blob, and file tokenizers stop at the known file size. Stream tokenizers reject with `EndOfStreamError` if the requested bytes are unavailable.
|
|
371
|
+
|
|
372
|
+
#### `close` function
|
|
373
|
+
Clean up resources, such as closing a file pointer if applicable.
|
|
374
|
+
|
|
375
|
+
```ts
|
|
376
|
+
close(): Promise<void>
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
Await this method when finished with a tokenizer. For Node.js streams, it does not destroy the underlying stream; the caller remains responsible for its lifecycle.
|
|
380
|
+
|
|
381
|
+
For Web streams, `close()` releases the reader lock. A BYOB reader leaves the source uncancelled, allowing another reader to continue reading it. A default reader cancels the source before releasing the lock, discarding remaining data. Bytes already read into tokenizer buffers, including peeked bytes, are not returned to the source.
|
|
382
|
+
|
|
383
|
+
#### `abort` function
|
|
384
|
+
|
|
385
|
+
Abort pending asynchronous stream operations.
|
|
386
|
+
|
|
387
|
+
```ts
|
|
388
|
+
abort(): Promise<void>
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
This is a no-op for buffer, blob, and file tokenizers.
|
|
392
|
+
|
|
393
|
+
For Web streams, `abort()` releases a BYOB reader's lock without cancelling the source. A default reader cancels the source but keeps its lock until `close()` is called. An `AbortSignal` invokes the same abort behavior.
|
|
394
|
+
|
|
395
|
+
#### `supportsRandomAccess` function
|
|
396
|
+
|
|
397
|
+
```ts
|
|
398
|
+
supportsRandomAccess(): boolean
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
Returns `true` for buffer, blob, and file tokenizers, and `false` for stream tokenizers.
|
|
402
|
+
When random access is supported, read and peek methods can use positions before `tokenizer.position`.
|
|
403
|
+
|
|
404
|
+
#### `setPosition` function
|
|
405
|
+
|
|
406
|
+
Available on buffer, blob, and file tokenizers (`IRandomAccessTokenizer`).
|
|
407
|
+
|
|
408
|
+
```ts
|
|
409
|
+
setPosition(position: number): void
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
Sets the current byte offset without reading data.
|
|
413
|
+
|
|
414
|
+
#### `Tokenizer` attributes
|
|
415
|
+
|
|
416
|
+
- `fileInfo`
|
|
417
|
+
|
|
418
|
+
Object containing optional file information, see [IFileInfo](#ifileinfo-interface).
|
|
419
|
+
|
|
420
|
+
- `position`
|
|
421
|
+
|
|
422
|
+
Pointer to the current position in the [*tokenizer*](#tokenizer-object) stream.
|
|
423
|
+
For stream tokenizers, a *position* provided to a _read_ or _peek_ method must be at least this value.
|
|
424
|
+
Buffer, blob, and file tokenizers also support earlier positions.
|
|
425
|
+
|
|
426
|
+
### `ITokenizerOptions` interface
|
|
427
|
+
|
|
428
|
+
Set these options once when creating a tokenizer. The configured limit applies to subsequent
|
|
429
|
+
reads and peeks for that tokenizer; no per-read limit is needed. Each attribute is optional:
|
|
430
|
+
|
|
431
|
+
| Attribute | Type | Description |
|
|
432
|
+
|-----------|------|-------------|
|
|
433
|
+
| maxBufferSize | number | Maximum bytes in a dynamically sized tokenizer buffer or stream lookahead span. Disabled by default (`Infinity`). Must be a positive safe integer or `Infinity`. |
|
|
434
|
+
| fileInfo | [IFileInfo](#ifileinfo-interface) | Additional metadata about the input |
|
|
435
|
+
| onClose | `() => Promise<void>` | Asynchronous callback invoked when a buffer, blob, or file tokenizer is closed |
|
|
436
|
+
| abortSignal | [AbortSignal](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal) | Signal used to abort asynchronous stream operations |
|
|
437
|
+
|
|
438
|
+
Creating a tokenizer with an already-aborted `abortSignal` throws or rejects with `AbortError`
|
|
439
|
+
before acquiring file handles or stream readers. Signal listeners are removed when the signal
|
|
440
|
+
fires or the tokenizer is closed, so closed tokenizers can be collected even when a signal is reused.
|
|
441
|
+
|
|
442
|
+
When `maxBufferSize` is configured, `readToken()` and `peekToken()` reject oversized buffers with `BufferSizeError`
|
|
443
|
+
before allocating or consuming input. The error exposes `requestedSize` and `maxBufferSize`.
|
|
444
|
+
Token lengths and positions must be non-negative safe integers. When the input size is known,
|
|
445
|
+
a token extending beyond the input rejects with `EndOfStreamError` before allocation.
|
|
446
|
+
|
|
447
|
+
For streams, the lookahead limit includes bytes between the current position and the requested
|
|
448
|
+
peek position. `mayBeLess: true` does not bypass this limit. With a finite cap, reads into
|
|
449
|
+
caller-provided buffers, Blob reads and `ignore()` use bounded chunks where internal buffers
|
|
450
|
+
are needed, so their total requested length may exceed `maxBufferSize`.
|
|
451
|
+
|
|
452
|
+
This limit does not cap total process memory, caller-owned input/output buffers, or allocations
|
|
453
|
+
inside a token's `get()` method. Stream sources may also supply chunks larger than this limit.
|
|
454
|
+
The cap is opt-in to preserve existing buffer sizes. Applications parsing untrusted input should
|
|
455
|
+
set a finite limit, for example 64 MiB. Omit the option or set it to `Infinity` to disable the cap.
|
|
456
|
+
|
|
457
|
+
```js
|
|
458
|
+
import { BufferSizeError, fromFile } from 'strtok3';
|
|
459
|
+
|
|
460
|
+
const tokenizer = await fromFile('somefile.bin', { maxBufferSize: 64 * 1024 * 1024 });
|
|
461
|
+
try {
|
|
462
|
+
// Read or peek tokens here.
|
|
463
|
+
} catch (error) {
|
|
464
|
+
if (error instanceof BufferSizeError) {
|
|
465
|
+
console.error(`Requested ${error.requestedSize} bytes; limit is ${error.maxBufferSize}`);
|
|
466
|
+
} else {
|
|
467
|
+
throw error;
|
|
468
|
+
}
|
|
469
|
+
} finally {
|
|
470
|
+
await tokenizer.close();
|
|
471
|
+
}
|
|
472
|
+
```
|
|
473
|
+
|
|
474
|
+
### `IReadChunkOptions` interface
|
|
475
|
+
|
|
476
|
+
Each attribute is optional:
|
|
477
|
+
|
|
478
|
+
| Attribute | Type | Description |
|
|
479
|
+
|-----------|---------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|
480
|
+
| length | number | Requested number of bytes to read or peek. Defaults to the target buffer length. |
|
|
481
|
+
| position | number | Byte offset to read or peek from. Defaults to [tokenizer.position](#tokenizer-attributes) when omitted. Earlier positions require random access. |
|
|
482
|
+
| mayBeLess | boolean | If `true`, allows fewer than the requested number of bytes to be read or peeked instead of throwing `EndOfStreamError`. Defaults to `false`. |
|
|
483
|
+
|
|
484
|
+
Example usage:
|
|
485
|
+
```js
|
|
486
|
+
const bytesPeeked = await tokenizer.peekBuffer(buffer, {mayBeLess: true});
|
|
487
|
+
```
|
|
488
|
+
|
|
489
|
+
### `IFileInfo` interface
|
|
490
|
+
|
|
491
|
+
Provides optional metadata about the file being tokenized.
|
|
492
|
+
|
|
493
|
+
| Attribute | Type | Description |
|
|
494
|
+
|-----------|---------|---------------------------------------------------------------------------------------------------|
|
|
495
|
+
| size | number | File size in bytes |
|
|
496
|
+
| mimeType | string | [MIME-type](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types) of file. |
|
|
497
|
+
| path | string | File path |
|
|
498
|
+
| url | string | File URL |
|
|
499
|
+
|
|
500
|
+
### `Token` object
|
|
501
|
+
|
|
502
|
+
The *token* is basically a description of what to read from the [*tokenizer-stream*](#tokenizer-object).
|
|
503
|
+
A basic set of *token types* can be found here: [*token-types*](https://github.com/Borewit/token-types).
|
|
504
|
+
|
|
505
|
+
A token is something which implements the following interface:
|
|
506
|
+
```ts
|
|
507
|
+
export interface IGetToken<T> {
|
|
508
|
+
|
|
509
|
+
/**
|
|
510
|
+
* Length in bytes of encoded value
|
|
511
|
+
*/
|
|
512
|
+
len: number;
|
|
513
|
+
|
|
514
|
+
/**
|
|
515
|
+
* Decode value from buffer at offset
|
|
516
|
+
* @param buf Buffer to read the decoded value from
|
|
517
|
+
* @param off Decode offset
|
|
518
|
+
*/
|
|
519
|
+
get(buf: Uint8Array, off: number): T;
|
|
520
|
+
}
|
|
521
|
+
```
|
|
522
|
+
The *tokenizer* reads `token.len` bytes from the *tokenizer-stream* into a Buffer.
|
|
523
|
+
The `token.get` will be called with the Buffer. `token.get` is responsible for conversion from the buffer to the desired output type.
|
|
524
|
+
|
|
525
|
+
### Working with a fetch response
|
|
526
|
+
|
|
527
|
+
Pass the response's [WHATWG readable stream](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream) directly to `fromWebStream`.
|
|
528
|
+
|
|
529
|
+
```js
|
|
530
|
+
import { fromWebStream } from 'strtok3';
|
|
531
|
+
import * as Token from 'token-types';
|
|
532
|
+
|
|
533
|
+
(async () => {
|
|
534
|
+
|
|
535
|
+
const response = await fetch(url);
|
|
536
|
+
if (!response.ok || !response.body) {
|
|
537
|
+
throw new Error(`Cannot read response: ${response.status}`);
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
const tokenizer = fromWebStream(response.body);
|
|
541
|
+
try {
|
|
542
|
+
const myNumber = await tokenizer.readToken(Token.UINT8);
|
|
543
|
+
console.log(`My number: ${myNumber}`);
|
|
544
|
+
} finally {
|
|
545
|
+
await tokenizer.close();
|
|
546
|
+
}
|
|
547
|
+
})();
|
|
548
|
+
```
|
|
549
|
+
|
|
550
|
+
## Dependencies
|
|
551
|
+
|
|
552
|
+
Dependencies:
|
|
553
|
+
- [@tokenizer/token](https://github.com/Borewit/tokenizer-token): Provides token definitions and utilities used by `strtok3` for interpreting binary data.
|
|
554
|
+
|
|
555
|
+
## Contributing
|
|
556
|
+
|
|
557
|
+
See [the contribution guide](CONTRIBUTING.md) for code style and development commands.
|
|
558
|
+
|
|
559
|
+
## Licence
|
|
560
|
+
|
|
561
|
+
This project is licensed under the [MIT License](LICENSE.txt). Feel free to use, modify, and distribute as needed.
|