@yume-chan/struct 0.0.19 → 0.0.20

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.
Files changed (42) hide show
  1. package/CHANGELOG.json +21 -0
  2. package/CHANGELOG.md +11 -1
  3. package/README.md +126 -143
  4. package/esm/basic/definition.d.ts +3 -3
  5. package/esm/basic/definition.d.ts.map +1 -1
  6. package/esm/basic/definition.js.map +1 -1
  7. package/esm/basic/stream.d.ts +11 -6
  8. package/esm/basic/stream.d.ts.map +1 -1
  9. package/esm/basic/stream.js +7 -1
  10. package/esm/basic/stream.js.map +1 -1
  11. package/esm/index.d.ts +1 -0
  12. package/esm/index.d.ts.map +1 -1
  13. package/esm/index.js +1 -0
  14. package/esm/index.js.map +1 -1
  15. package/esm/struct.d.ts +19 -9
  16. package/esm/struct.d.ts.map +1 -1
  17. package/esm/struct.js +57 -25
  18. package/esm/struct.js.map +1 -1
  19. package/esm/sync-promise.js +12 -12
  20. package/esm/sync-promise.js.map +1 -1
  21. package/esm/types/bigint.d.ts +3 -3
  22. package/esm/types/bigint.d.ts.map +1 -1
  23. package/esm/types/bigint.js +1 -1
  24. package/esm/types/bigint.js.map +1 -1
  25. package/esm/types/buffer/base.d.ts +3 -3
  26. package/esm/types/buffer/base.d.ts.map +1 -1
  27. package/esm/types/buffer/base.js +1 -1
  28. package/esm/types/buffer/base.js.map +1 -1
  29. package/esm/types/number.d.ts +3 -3
  30. package/esm/types/number.d.ts.map +1 -1
  31. package/esm/types/number.js +14 -16
  32. package/esm/types/number.js.map +1 -1
  33. package/package.json +6 -6
  34. package/src/basic/definition.ts +3 -6
  35. package/src/basic/stream.ts +17 -6
  36. package/src/index.ts +1 -0
  37. package/src/struct.ts +79 -46
  38. package/src/sync-promise.ts +12 -12
  39. package/src/types/bigint.ts +6 -6
  40. package/src/types/buffer/base.ts +6 -6
  41. package/src/types/number.ts +23 -27
  42. package/tsconfig.build.tsbuildinfo +1 -1
package/CHANGELOG.json CHANGED
@@ -1,6 +1,27 @@
1
1
  {
2
2
  "name": "@yume-chan/struct",
3
3
  "entries": [
4
+ {
5
+ "version": "0.0.20",
6
+ "tag": "@yume-chan/struct_v0.0.20",
7
+ "date": "Mon, 05 Jun 2023 02:51:41 GMT",
8
+ "comments": {
9
+ "none": [
10
+ {
11
+ "comment": "Rename `StructDeserializeStream` and `StructAsyncDeserializeStream` to `ExactReadable` and `AsyncExactReadable`. Rename its `read` method to `readExactly`. Add a `position` field so the caller can check how many bytes have been read."
12
+ },
13
+ {
14
+ "comment": "Improve performance for decoding integers."
15
+ },
16
+ {
17
+ "comment": "Rename `Struct#fields` to `Struct#concat`. Now `Struct#fields` returns an array of `[name: PropertyKey, definition: StructFieldDefinition<any, any, any>]` tuples."
18
+ },
19
+ {
20
+ "comment": "Use ECMAScript private class fields syntax (supported by Chrome 74, Firefox 90, Safari 14.1 and Node.js 12.0.0)."
21
+ }
22
+ ]
23
+ }
24
+ },
4
25
  {
5
26
  "version": "0.0.19",
6
27
  "tag": "@yume-chan/struct_v0.0.19",
package/CHANGELOG.md CHANGED
@@ -1,6 +1,16 @@
1
1
  # Change Log - @yume-chan/struct
2
2
 
3
- This log was last generated on Sun, 09 Apr 2023 05:55:33 GMT and should not be manually modified.
3
+ This log was last generated on Mon, 05 Jun 2023 02:51:41 GMT and should not be manually modified.
4
+
5
+ ## 0.0.20
6
+ Mon, 05 Jun 2023 02:51:41 GMT
7
+
8
+ ### Updates
9
+
10
+ - Rename `StructDeserializeStream` and `StructAsyncDeserializeStream` to `ExactReadable` and `AsyncExactReadable`. Rename its `read` method to `readExactly`. Add a `position` field so the caller can check how many bytes have been read.
11
+ - Improve performance for decoding integers.
12
+ - Rename `Struct#fields` to `Struct#concat`. Now `Struct#fields` returns an array of `[name: PropertyKey, definition: StructFieldDefinition<any, any, any>]` tuples.
13
+ - Use ECMAScript private class fields syntax (supported by Chrome 74, Firefox 90, Safari 14.1 and Node.js 12.0.0).
4
14
 
5
15
  ## 0.0.19
6
16
  Sun, 09 Apr 2023 05:55:33 GMT
package/README.md CHANGED
@@ -13,7 +13,7 @@ cspell: ignore uint8arraystring
13
13
 
14
14
  A C-style structure serializer and deserializer. Written in TypeScript and highly takes advantage of its type system.
15
15
 
16
- **WARNING:** The public API is UNSTABLE. If you have any questions, please open an issue.
16
+ **WARNING:** The public API is UNSTABLE. Open a GitHub discussion if you have any questions.
17
17
 
18
18
  ## Installation
19
19
 
@@ -24,60 +24,59 @@ $ npm i @yume-chan/struct
24
24
  ## Quick Start
25
25
 
26
26
  ```ts
27
- import Struct from '@yume-chan/struct';
27
+ import Struct from "@yume-chan/struct";
28
28
 
29
- const MyStruct =
30
- new Struct({ littleEndian: true })
31
- .int8('foo')
32
- .int64('bar')
33
- .int32('bazLength')
34
- .string('baz', { lengthField: 'bazLength' });
29
+ const MyStruct = new Struct({ littleEndian: true })
30
+ .int8("foo")
31
+ .int64("bar")
32
+ .int32("bazLength")
33
+ .string("baz", { lengthField: "bazLength" });
35
34
 
36
35
  const value = await MyStruct.deserialize(stream);
37
- value.foo // number
38
- value.bar // bigint
39
- value.bazLength // number
40
- value.baz // string
36
+ value.foo; // number
37
+ value.bar; // bigint
38
+ value.bazLength; // number
39
+ value.baz; // string
41
40
 
42
41
  const buffer = MyStruct.serialize({
43
42
  foo: 42,
44
43
  bar: 42n,
45
44
  // `bazLength` automatically set to `baz`'s byte length
46
- baz: 'Hello, World!',
45
+ baz: "Hello, World!",
47
46
  });
48
47
  ```
49
48
 
50
49
  <!-- cspell: disable -->
51
50
 
52
- - [Installation](#installation)
53
- - [Quick Start](#quick-start)
54
- - [Compatibility](#compatibility)
55
- - [Basic usage](#basic-usage)
56
- - [`int64`/`uint64`](#int64uint64)
57
- - [`string`](#string)
58
- - [API](#api)
59
- - [`placeholder`](#placeholder)
60
- - [`Struct`](#struct)
61
- - [`int8`/`uint8`/`int16`/`uint16`/`int32`/`uint32`](#int8uint8int16uint16int32uint32)
62
- - [`int64`/`uint64`](#int64uint64-1)
63
- - [`uint8Array`/`string`](#uint8arraystring)
64
- - [`fields`](#fields)
65
- - [`extra`](#extra)
66
- - [`postDeserialize`](#postdeserialize)
67
- - [`deserialize`](#deserialize)
68
- - [`serialize`](#serialize)
69
- - [Custom field type](#custom-field-type)
70
- - [`Struct#field`](#structfield)
71
- - [Relationship between types](#relationship-between-types)
72
- - [`StructFieldDefinition`](#structfielddefinition)
73
- - [`TValue`/`TOmitInitKey`](#tvaluetomitinitkey)
74
- - [`getSize`](#getsize)
75
- - [`create`](#create)
76
- - [`deserialize`](#deserialize-1)
77
- - [`StructFieldValue`](#structfieldvalue)
78
- - [`getSize`](#getsize-1)
79
- - [`get`/`set`](#getset)
80
- - [`serialize`](#serialize-1)
51
+ - [Installation](#installation)
52
+ - [Quick Start](#quick-start)
53
+ - [Compatibility](#compatibility)
54
+ - [Basic usage](#basic-usage)
55
+ - [`int64`/`uint64`](#int64uint64)
56
+ - [`string`](#string)
57
+ - [API](#api)
58
+ - [`placeholder`](#placeholder)
59
+ - [`Struct`](#struct)
60
+ - [`int8`/`uint8`/`int16`/`uint16`/`int32`/`uint32`](#int8uint8int16uint16int32uint32)
61
+ - [`int64`/`uint64`](#int64uint64-1)
62
+ - [`uint8Array`/`string`](#uint8arraystring)
63
+ - [`concat`](#concat)
64
+ - [`extra`](#extra)
65
+ - [`postDeserialize`](#postdeserialize)
66
+ - [`deserialize`](#deserialize)
67
+ - [`serialize`](#serialize)
68
+ - [Custom field type](#custom-field-type)
69
+ - [`Struct#field`](#structfield)
70
+ - [Relationship between types](#relationship-between-types)
71
+ - [`StructFieldDefinition`](#structfielddefinition)
72
+ - [`TValue`/`TOmitInitKey`](#tvaluetomitinitkey)
73
+ - [`getSize`](#getsize)
74
+ - [`create`](#create)
75
+ - [`deserialize`](#deserialize-1)
76
+ - [`StructFieldValue`](#structfieldvalue)
77
+ - [`getSize`](#getsize-1)
78
+ - [`get`/`set`](#getset)
79
+ - [`serialize`](#serialize-1)
81
80
 
82
81
  <!-- cspell: enable -->
83
82
 
@@ -91,17 +90,17 @@ Some features can be polyfilled to support older runtimes, but this library does
91
90
 
92
91
  | API | Chrome | Edge | Firefox | Internet Explorer | Safari | Node.js |
93
92
  | -------------------------------- | ------ | ---- | ------- | ----------------- | ------ | ------- |
94
- | [`Promise`][MDN_Promise] | 32 | 12 | 29 | No | 8 | 0.12 |
95
- | [`ArrayBuffer`][MDN_ArrayBuffer] | 7 | 12 | 4 | 10 | 5.1 | 0.10 |
96
- | [`Uint8Array`][MDN_Uint8Array] | 7 | 12 | 4 | 10 | 5.1 | 0.10 |
97
- | [`DataView`][MDN_DataView] | 9 | 12 | 15 | 10 | 5.1 | 0.10 |
98
- | *Overall* | 32 | 12 | 29 | No | 8 | 0.12 |
93
+ | [`Promise`][mdn_promise] | 32 | 12 | 29 | No | 8 | 0.12 |
94
+ | [`ArrayBuffer`][mdn_arraybuffer] | 7 | 12 | 4 | 10 | 5.1 | 0.10 |
95
+ | [`Uint8Array`][mdn_uint8array] | 7 | 12 | 4 | 10 | 5.1 | 0.10 |
96
+ | [`DataView`][mdn_dataview] | 9 | 12 | 15 | 10 | 5.1 | 0.10 |
97
+ | _Overall_ | 32 | 12 | 29 | No | 8 | 0.12 |
99
98
 
100
99
  ### [`int64`/`uint64`](#int64uint64-1)
101
100
 
102
101
  | API | Chrome | Edge | Firefox | Internet Explorer | Safari | Node.js |
103
102
  | ---------------------------------- | ------ | ---- | ------- | ----------------- | ------ | ------- |
104
- | [`BigInt`][MDN_BigInt]<sup>1</sup> | 67 | 79 | 68 | No | 14 | 10.4 |
103
+ | [`BigInt`][mdn_bigint]<sup>1</sup> | 67 | 79 | 68 | No | 14 | 10.4 |
105
104
 
106
105
  <sup>1</sup> Can't be polyfilled
107
106
 
@@ -109,17 +108,17 @@ Some features can be polyfilled to support older runtimes, but this library does
109
108
 
110
109
  | API | Chrome | Edge | Firefox | Internet Explorer | Safari | Node.js |
111
110
  | -------------------------------- | ------ | ---- | ------- | ----------------- | ------ | ------------------- |
112
- | [`TextEncoder`][MDN_TextEncoder] | 38 | 79 | 19 | No | 10.1 | 8.3<sup>1</sup>, 11 |
111
+ | [`TextEncoder`][mdn_textencoder] | 38 | 79 | 19 | No | 10.1 | 8.3<sup>1</sup>, 11 |
113
112
 
114
113
  <sup>1</sup> `TextEncoder` and `TextDecoder` are only available in `util` module. Need to be assigned to `globalThis`.
115
114
 
116
- [MDN_Promise]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
117
- [MDN_ArrayBuffer]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer
118
- [MDN_Uint8Array]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array
119
- [MDN_DataView]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView
120
- [MDN_BigInt]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt
121
- [MDN_DataView]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView
122
- [MDN_TextEncoder]: https://developer.mozilla.org/en-US/docs/Web/API/TextEncoder
115
+ [mdn_promise]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
116
+ [mdn_arraybuffer]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer
117
+ [mdn_uint8array]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array
118
+ [mdn_dataview]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView
119
+ [mdn_bigint]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt
120
+ [mdn_dataview]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView
121
+ [mdn_textencoder]: https://developer.mozilla.org/en-US/docs/Web/API/TextEncoder
123
122
 
124
123
  ## API
125
124
 
@@ -154,9 +153,10 @@ declare function fn2<A, B>(a: A, b: B): [A, B];
154
153
  I don't really need a value of type `B`, I only require its type information
155
154
 
156
155
  ```ts
157
- fn2(42, placeholder<boolean>()) // fn2<number, boolean>
156
+ fn2(42, placeholder<boolean>()); // fn2<number, boolean>
158
157
  ```
159
- </details>
158
+
159
+ </details><br/>
160
160
 
161
161
  To workaround this issue, these methods have an extra `_typescriptType` parameter, to let you specify a generic parameter, without passing all other generic arguments manually. The actual value of `_typescriptType` argument is never used, so you can pass any value, as long as it has the correct type, including values produced by this `placeholder` method.
162
162
 
@@ -186,14 +186,15 @@ This information was added to help you understand how does it work. These are co
186
186
  2. `TOmitInitKey`: When serializing a structure containing variable length buffers, the length field can be calculate from the buffer field, so they doesn't need to be provided explicitly.
187
187
  3. `TExtra`: Type of extra fields. Modified when `extra` is called.
188
188
  4. `TPostDeserialized`: State of the `postDeserialize` function. Modified when `postDeserialize` is called. Affects return type of `deserialize`
189
- </details>
189
+
190
+ </details><br/>
190
191
 
191
192
  **Parameters**
192
193
 
193
194
  1. `options`:
194
- * `littleEndian:boolean = false`: Whether all multi-byte fields in this struct are [little-endian encoded][Wikipeida_Endianess].
195
+ - `littleEndian:boolean = false`: Whether all multi-byte fields in this struct are [little-endian encoded][wikipeida_endianess].
195
196
 
196
- [Wikipeida_Endianess]: https://en.wikipedia.org/wiki/Endianness
197
+ [wikipeida_endianess]: https://en.wikipedia.org/wiki/Endianness
197
198
 
198
199
  #### `int8`/`uint8`/`int16`/`uint16`/`int32`/`uint32`
199
200
 
@@ -219,7 +220,8 @@ Appends an `int8`/`uint8`/`int16`/`uint16`/`int32`/`uint32` field to the `Struct
219
220
 
220
221
  1. `TName`: Literal type of the field's name.
221
222
  2. `TTypeScriptType = number`: Type of the field in the result object. For example you can declare it as a number literal type, or some enum type.
222
- </details>
223
+
224
+ </details><br/>
223
225
 
224
226
  **Parameters**
225
227
 
@@ -237,18 +239,17 @@ So it's technically possible to pass in an incompatible type (e.g. `string`). Bu
237
239
  1. Append an `int32` field named `foo`
238
240
 
239
241
  ```ts
240
- const struct = new Struct()
241
- .int32('foo');
242
+ const struct = new Struct().int32("foo");
242
243
 
243
244
  const value = await struct.deserialize(stream);
244
245
  value.foo; // number
245
246
 
246
- struct.serialize({ }) // error: 'foo' is required
247
- struct.serialize({ foo: 'bar' }) // error: 'foo' must be a number
248
- struct.serialize({ foo: 42 }) // ok
247
+ struct.serialize({}); // error: 'foo' is required
248
+ struct.serialize({ foo: "bar" }); // error: 'foo' must be a number
249
+ struct.serialize({ foo: 42 }); // ok
249
250
  ```
250
251
 
251
- 2. Set fields' type (can be used with [`placeholder` method](#placeholder))
252
+ 2. Set fields' type (can use [`placeholder` method](#placeholder))
252
253
 
253
254
  ```ts
254
255
  enum MyEnum {
@@ -257,8 +258,8 @@ So it's technically possible to pass in an incompatible type (e.g. `string`). Bu
257
258
  }
258
259
 
259
260
  const struct = new Struct()
260
- .int32('foo', placeholder<MyEnum>())
261
- .int32('bar', MyEnum.a as const);
261
+ .int32("foo", placeholder<MyEnum>())
262
+ .int32("bar", MyEnum.a as const);
262
263
 
263
264
  const value = await struct.deserialize(stream);
264
265
  value.foo; // MyEnum
@@ -326,15 +327,15 @@ uint8Array<
326
327
 
327
328
  Appends an `uint8Array`/`string` field to the `Struct`.
328
329
 
329
- The `options` parameter defines its length, it can be in two formats:
330
+ The `options` parameter defines its length, it supports two formats:
330
331
 
331
- * `{ length: number }`: Presence of the `length` option indicates that it's a fixed length array.
332
- * `{ lengthField: string; lengthFieldRadix?: number }`: Presence of the `lengthField` option indicates it's a variable length array. The `lengthField` options must refers to a `number` or `string` (can't be `bigint`) typed field that's already defined in this `Struct`. If the length field is a `string`, the optional `lengthFieldRadix` option (defaults to `10`) defines the radix when converting the string to a number. When deserializing, it will use that field's value as its length. When serializing, it will write its length to that field.
332
+ - `{ length: number }`: Presence of the `length` option indicates that it's a fixed length array.
333
+ - `{ lengthField: string; lengthFieldRadix?: number }`: Presence of the `lengthField` option indicates it's a variable length array. The `lengthField` options must refers to a `number` or `string` (can't be `bigint`) typed field that's already defined in this `Struct`. If the length field is a `string`, the optional `lengthFieldRadix` option (defaults to `10`) defines the radix when converting the string to a number. When deserializing, it will use that field's value as its length. When serializing, it will write its length to that field.
333
334
 
334
- #### `fields`
335
+ #### `concat`
335
336
 
336
337
  ```ts
337
- fields<
338
+ concat<
338
339
  TOther extends Struct<any, any, any, any>
339
340
  >(
340
341
  other: TOther
@@ -353,14 +354,9 @@ Merges (flats) another `Struct`'s fields and extra fields into the current one.
353
354
  1. Extending another `Struct`
354
355
 
355
356
  ```ts
356
- const MyStructV1 =
357
- new Struct()
358
- .int32('field1');
357
+ const MyStructV1 = new Struct().int32("field1");
359
358
 
360
- const MyStructV2 =
361
- new Struct()
362
- .fields(MyStructV1)
363
- .int32('field2');
359
+ const MyStructV2 = new Struct().concat(MyStructV1).int32("field2");
364
360
 
365
361
  const structV2 = await MyStructV2.deserialize(stream);
366
362
  structV2.field1; // number
@@ -371,14 +367,9 @@ Merges (flats) another `Struct`'s fields and extra fields into the current one.
371
367
  2. Also possible in any order
372
368
 
373
369
  ```ts
374
- const MyStructV1 =
375
- new Struct()
376
- .int32('field1');
370
+ const MyStructV1 = new Struct().int32("field1");
377
371
 
378
- const MyStructV2 =
379
- new Struct()
380
- .int32('field2')
381
- .fields(MyStructV1);
372
+ const MyStructV2 = new Struct().int32("field2").concat(MyStructV1);
382
373
 
383
374
  const structV2 = await MyStructV2.deserialize(stream);
384
375
  structV2.field1; // number
@@ -427,35 +418,31 @@ Multiple calls merge all extra fields together.
427
418
  1. Add an extra field
428
419
 
429
420
  ```ts
430
- const struct = new Struct()
431
- .int32('foo')
432
- .extra({
433
- bar: 'hello',
434
- });
421
+ const struct = new Struct().int32("foo").extra({
422
+ bar: "hello",
423
+ });
435
424
 
436
425
  const value = await struct.deserialize(stream);
437
426
  value.foo; // number
438
427
  value.bar; // 'hello'
439
428
 
440
429
  struct.serialize({ foo: 42 }); // ok
441
- struct.serialize({ foo: 42, bar: 'hello' }); // error: 'bar' is redundant
430
+ struct.serialize({ foo: 42, bar: "hello" }); // error: 'bar' is redundant
442
431
  ```
443
432
 
444
433
  2. Add getters and methods. `this` in functions refers to the result object.
445
434
 
446
435
  ```ts
447
- const struct = new Struct()
448
- .int32('foo')
449
- .extra({
450
- get bar() {
451
- // `this` is the result Struct value
452
- return this.foo + 1;
453
- },
454
- logBar() {
455
- // `this` also contains other extra fields
456
- console.log(this.bar);
457
- },
458
- });
436
+ const struct = new Struct().int32("foo").extra({
437
+ get bar() {
438
+ // `this` is the result Struct value
439
+ return this.foo + 1;
440
+ },
441
+ logBar() {
442
+ // `this` also contains other extra fields
443
+ console.log(this.bar);
444
+ },
445
+ });
459
446
 
460
447
  const value = await struct.deserialize(stream);
461
448
  value.foo; // number
@@ -516,9 +503,9 @@ A callback returning anything other than `undefined` will cause `deserialize` to
516
503
  // But you don't want to modify all receiving path
517
504
 
518
505
  const struct = new Struct()
519
- .int32('messageLength')
520
- .string('message', { lengthField: 'messageLength' })
521
- .postDeserialize(value => {
506
+ .int32("messageLength")
507
+ .string("message", { lengthField: "messageLength" })
508
+ .postDeserialize((value) => {
522
509
  throw new Error(value.message);
523
510
  });
524
511
  ```
@@ -532,50 +519,53 @@ A callback returning anything other than `undefined` will cause `deserialize` to
532
519
  3. Replace result object
533
520
 
534
521
  ```ts
535
- const struct1 = new Struct()
536
- .int32('foo')
537
- .postDeserialize(value => {
538
- return {
539
- bar: value.foo,
540
- };
541
- });
522
+ const struct1 = new Struct().int32("foo").postDeserialize((value) => {
523
+ return {
524
+ bar: value.foo,
525
+ };
526
+ });
542
527
 
543
528
  const value = await struct.deserialize(stream);
544
- value.foo // error: not exist
529
+ value.foo; // error: not exist
545
530
  value.bar; // number
546
531
  ```
547
532
 
548
533
  #### `deserialize`
549
534
 
550
535
  ```ts
551
- interface StructDeserializeStream {
536
+
537
+ interface ExactReadable {
538
+ readonly position: number;
539
+
552
540
  /**
553
541
  * Read data from the underlying data source.
554
542
  *
555
543
  * The stream must return exactly `length` bytes or data. If that's not possible
556
- * (due to end of file or other error condition), it must throw an error.
544
+ * (due to end of file or other error condition), it must throw an {@link ExactReadableEndedError}.
557
545
  */
558
- read(length: number): Uint8Array;
546
+ readExactly(length: number): Uint8Array;
559
547
  }
560
548
 
561
- interface StructAsyncDeserializeStream {
549
+ interface AsyncExactReadable {
550
+ readonly position: number;
551
+
562
552
  /**
563
553
  * Read data from the underlying data source.
564
554
  *
565
555
  * The stream must return exactly `length` bytes or data. If that's not possible
566
- * (due to end of file or other error condition), it must throw an error.
556
+ * (due to end of file or other error condition), it must throw an {@link ExactReadableEndedError}.
567
557
  */
568
- read(length: number): Promise<Uint8Array>;
558
+ readExactly(length: number): ValueOrPromise<Uint8Array>;
569
559
  }
570
560
 
571
561
  deserialize(
572
- stream: StructDeserializeStream,
562
+ stream: ExactReadable,
573
563
  ): TPostDeserialized extends undefined
574
564
  ? Overwrite<TExtra, TValue>
575
565
  : TPostDeserialized
576
566
  >;
577
567
  deserialize(
578
- stream: StructAsyncDeserializeStream,
568
+ stream: AsyncExactReadable,
579
569
  ): Promise<
580
570
  TPostDeserialized extends undefined
581
571
  ? Overwrite<TExtra, TValue>
@@ -590,8 +580,6 @@ It will be synchronous (returns a value) or asynchronous (returns a `Promise`) d
590
580
 
591
581
  As the signature shows, if the `postDeserialize` callback returns any value, `deserialize` will return that value instead.
592
582
 
593
- The `read` method of `stream`, when being called, should returns exactly `length` bytes of data (or throw an `Error` if it can't).
594
-
595
583
  #### `serialize`
596
584
 
597
585
  ```ts
@@ -629,27 +617,22 @@ Appends a `StructFieldDefinition` to the `Struct`.
629
617
  All built-in field type methods are actually aliases to it. For example, calling
630
618
 
631
619
  ```ts
632
- struct.int8('foo')
620
+ struct.int8("foo");
633
621
  ```
634
622
 
635
623
  is same as
636
624
 
637
625
  ```ts
638
- struct.field(
639
- 'foo',
640
- new NumberFieldDefinition(
641
- NumberFieldType.Int8
642
- )
643
- )
626
+ struct.field("foo", new NumberFieldDefinition(NumberFieldType.Int8));
644
627
  ```
645
628
 
646
629
  ### Relationship between types
647
630
 
648
- * `StructFieldValue`: Contains value of a field, with optional metadata and accessor methods.
649
- * `StructFieldDefinition`: Definition of a field, can deserialize `StructFieldValue`s from a stream or create them from exist values.
650
- * `StructValue`: A map between field names and `StructFieldValue`s.
651
- * `Struct`: Definiton of a struct, a map between field names and `StructFieldDefintion`s. May contain extra metadata.
652
- * Result of `Struct#deserialize()`: A map between field names and results of `StructFieldValue#get()`.
631
+ - `StructFieldValue`: Contains value of a field, with optional metadata and accessor methods.
632
+ - `StructFieldDefinition`: Definition of a field, can deserialize `StructFieldValue`s from a stream or create them from exist values.
633
+ - `StructValue`: A map between field names and `StructFieldValue`s.
634
+ - `Struct`: Definition of a struct, a map between field names and `StructFieldDefintion`s. May contain extra metadata.
635
+ - Result of `Struct#deserialize()`: A map between field names and results of `StructFieldValue#get()`.
653
636
 
654
637
  ### `StructFieldDefinition`
655
638
 
@@ -657,7 +640,7 @@ struct.field(
657
640
  abstract class StructFieldDefinition<
658
641
  TOptions = void,
659
642
  TValue = unknown,
660
- TOmitInitKey extends PropertyKey = never,
643
+ TOmitInitKey extends PropertyKey = never
661
644
  > {
662
645
  public readonly options: TOptions;
663
646
 
@@ -702,12 +685,12 @@ Derived classes must implement this method to create its own field value instanc
702
685
  ```ts
703
686
  abstract deserialize(
704
687
  options: Readonly<StructOptions>,
705
- stream: StructDeserializeStream,
688
+ stream: ExactReadable,
706
689
  struct: StructValue,
707
690
  ): StructFieldValue<this>;
708
691
  abstract deserialize(
709
692
  options: Readonly<StructOptions>,
710
- stream: StructAsyncDeserializeStream,
693
+ stream: AsyncExactReadable,
711
694
  struct: StructValue,
712
695
  ): Promise<StructFieldValue<this>>;
713
696
  ```
@@ -1,6 +1,6 @@
1
1
  import type { StructFieldValue } from "./field-value.js";
2
2
  import type { StructOptions } from "./options.js";
3
- import type { StructAsyncDeserializeStream, StructDeserializeStream } from "./stream.js";
3
+ import type { AsyncExactReadable, ExactReadable } from "./stream.js";
4
4
  import type { StructValue } from "./struct-value.js";
5
5
  /**
6
6
  * A field definition defines how to deserialize a field.
@@ -38,7 +38,7 @@ export declare abstract class StructFieldDefinition<TOptions = void, TValue = un
38
38
  *
39
39
  * `SyncPromise` can be used to simplify implementation.
40
40
  */
41
- abstract deserialize(options: Readonly<StructOptions>, stream: StructDeserializeStream, structValue: StructValue): StructFieldValue<this>;
42
- abstract deserialize(options: Readonly<StructOptions>, stream: StructAsyncDeserializeStream, struct: StructValue): Promise<StructFieldValue<this>>;
41
+ abstract deserialize(options: Readonly<StructOptions>, stream: ExactReadable, structValue: StructValue): StructFieldValue<this>;
42
+ abstract deserialize(options: Readonly<StructOptions>, stream: AsyncExactReadable, struct: StructValue): Promise<StructFieldValue<this>>;
43
43
  }
44
44
  //# sourceMappingURL=definition.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"definition.d.ts","sourceRoot":"","sources":["../../src/basic/definition.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,KAAK,EACR,4BAA4B,EAC5B,uBAAuB,EAC1B,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD;;;;;;GAMG;AACH,8BAAsB,qBAAqB,CACvC,QAAQ,GAAG,IAAI,EACf,MAAM,GAAG,OAAO,EAChB,YAAY,SAAS,WAAW,GAAG,KAAK;IAExC;;;OAGG;IACH,SAAgB,MAAM,EAAG,MAAM,CAAC;IAEhC;;;OAGG;IACH,SAAgB,YAAY,EAAG,YAAY,CAAC;IAE5C,SAAgB,OAAO,EAAE,QAAQ,CAAC;gBAEf,OAAO,EAAE,QAAQ;IAIpC;;;;OAIG;aACa,OAAO,IAAI,MAAM;IAEjC;;OAEG;aACa,MAAM,CAClB,OAAO,EAAE,QAAQ,CAAC,aAAa,CAAC,EAChC,WAAW,EAAE,WAAW,EACxB,KAAK,EAAE,MAAM,GACd,gBAAgB,CAAC,IAAI,CAAC;IAEzB;;;;;OAKG;aACa,WAAW,CACvB,OAAO,EAAE,QAAQ,CAAC,aAAa,CAAC,EAChC,MAAM,EAAE,uBAAuB,EAC/B,WAAW,EAAE,WAAW,GACzB,gBAAgB,CAAC,IAAI,CAAC;aACT,WAAW,CACvB,OAAO,EAAE,QAAQ,CAAC,aAAa,CAAC,EAChC,MAAM,EAAE,4BAA4B,EACpC,MAAM,EAAE,WAAW,GACpB,OAAO,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;CACrC"}
1
+ {"version":3,"file":"definition.d.ts","sourceRoot":"","sources":["../../src/basic/definition.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,KAAK,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACrE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD;;;;;;GAMG;AACH,8BAAsB,qBAAqB,CACvC,QAAQ,GAAG,IAAI,EACf,MAAM,GAAG,OAAO,EAChB,YAAY,SAAS,WAAW,GAAG,KAAK;IAExC;;;OAGG;IACH,SAAgB,MAAM,EAAG,MAAM,CAAC;IAEhC;;;OAGG;IACH,SAAgB,YAAY,EAAG,YAAY,CAAC;IAE5C,SAAgB,OAAO,EAAE,QAAQ,CAAC;gBAEf,OAAO,EAAE,QAAQ;IAIpC;;;;OAIG;aACa,OAAO,IAAI,MAAM;IAEjC;;OAEG;aACa,MAAM,CAClB,OAAO,EAAE,QAAQ,CAAC,aAAa,CAAC,EAChC,WAAW,EAAE,WAAW,EACxB,KAAK,EAAE,MAAM,GACd,gBAAgB,CAAC,IAAI,CAAC;IAEzB;;;;;OAKG;aACa,WAAW,CACvB,OAAO,EAAE,QAAQ,CAAC,aAAa,CAAC,EAChC,MAAM,EAAE,aAAa,EACrB,WAAW,EAAE,WAAW,GACzB,gBAAgB,CAAC,IAAI,CAAC;aACT,WAAW,CACvB,OAAO,EAAE,QAAQ,CAAC,aAAa,CAAC,EAChC,MAAM,EAAE,kBAAkB,EAC1B,MAAM,EAAE,WAAW,GACpB,OAAO,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;CACrC"}
@@ -1 +1 @@
1
- {"version":3,"file":"definition.js","sourceRoot":"","sources":["../../src/basic/definition.ts"],"names":[],"mappings":"AAQA;;;;;;GAMG;AACH,MAAM,OAAgB,qBAAqB;IAKvC;;;OAGG;IACa,MAAM,CAAU;IAEhC;;;OAGG;IACa,YAAY,CAAgB;IAE5B,OAAO,CAAW;IAElC,YAAmB,OAAiB;QAChC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IAC3B,CAAC;CAkCJ"}
1
+ {"version":3,"file":"definition.js","sourceRoot":"","sources":["../../src/basic/definition.ts"],"names":[],"mappings":"AAKA;;;;;;GAMG;AACH,MAAM,OAAgB,qBAAqB;IAKvC;;;OAGG;IACa,MAAM,CAAU;IAEhC;;;OAGG;IACa,YAAY,CAAgB;IAE5B,OAAO,CAAW;IAElC,YAAmB,OAAiB;QAChC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IAC3B,CAAC;CAkCJ"}
@@ -1,20 +1,25 @@
1
1
  import type { ValueOrPromise } from "../utils.js";
2
- export interface StructDeserializeStream {
2
+ export declare class ExactReadableEndedError extends Error {
3
+ constructor();
4
+ }
5
+ export interface ExactReadable {
6
+ readonly position: number;
3
7
  /**
4
8
  * Read data from the underlying data source.
5
9
  *
6
10
  * The stream must return exactly `length` bytes or data. If that's not possible
7
- * (due to end of file or other error condition), it must throw an error.
11
+ * (due to end of file or other error condition), it must throw an {@link ExactReadableEndedError}.
8
12
  */
9
- read(length: number): Uint8Array;
13
+ readExactly(length: number): Uint8Array;
10
14
  }
11
- export interface StructAsyncDeserializeStream {
15
+ export interface AsyncExactReadable {
16
+ readonly position: number;
12
17
  /**
13
18
  * Read data from the underlying data source.
14
19
  *
15
20
  * The stream must return exactly `length` bytes or data. If that's not possible
16
- * (due to end of file or other error condition), it must throw an error.
21
+ * (due to end of file or other error condition), it must throw an {@link ExactReadableEndedError}.
17
22
  */
18
- read(length: number): ValueOrPromise<Uint8Array>;
23
+ readExactly(length: number): ValueOrPromise<Uint8Array>;
19
24
  }
20
25
  //# sourceMappingURL=stream.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../../src/basic/stream.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAIlD,MAAM,WAAW,uBAAuB;IACpC;;;;;OAKG;IACH,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,CAAC;CACpC;AAED,MAAM,WAAW,4BAA4B;IACzC;;;;;OAKG;IACH,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc,CAAC,UAAU,CAAC,CAAC;CACpD"}
1
+ {"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../../src/basic/stream.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAIlD,qBAAa,uBAAwB,SAAQ,KAAK;;CAKjD;AAED,MAAM,WAAW,aAAa;IAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAE1B;;;;;OAKG;IACH,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,CAAC;CAC3C;AAED,MAAM,WAAW,kBAAkB;IAC/B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAE1B;;;;;OAKG;IACH,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc,CAAC,UAAU,CAAC,CAAC;CAC3D"}
@@ -1,2 +1,8 @@
1
- export {};
1
+ // TODO: allow over reading (returning a `Uint8Array`, an `offset` and a `length`) to avoid copying
2
+ export class ExactReadableEndedError extends Error {
3
+ constructor() {
4
+ super("ExactReadable ended");
5
+ Object.setPrototypeOf(this, new.target.prototype);
6
+ }
7
+ }
2
8
  //# sourceMappingURL=stream.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"stream.js","sourceRoot":"","sources":["../../src/basic/stream.ts"],"names":[],"mappings":""}
1
+ {"version":3,"file":"stream.js","sourceRoot":"","sources":["../../src/basic/stream.ts"],"names":[],"mappings":"AAEA,mGAAmG;AAEnG,MAAM,OAAO,uBAAwB,SAAQ,KAAK;IAC9C;QACI,KAAK,CAAC,qBAAqB,CAAC,CAAC;QAC7B,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IACtD,CAAC;CACJ"}
package/esm/index.d.ts CHANGED
@@ -9,6 +9,7 @@ declare global {
9
9
  export * from "./basic/index.js";
10
10
  export * from "./struct.js";
11
11
  export { Struct as default } from "./struct.js";
12
+ export * from "./sync-promise.js";
12
13
  export * from "./types/index.js";
13
14
  export * from "./utils.js";
14
15
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,CAAC,MAAM,CAAC;IACX,UAAU,WAAW;QAEjB,OAAO,EAAE,KAAK,CAAC;KAClB;IAED,UAAU,iBAAiB;QAEvB,OAAO,EAAE,KAAK,CAAC;KAClB;CACJ;AAED,cAAc,kBAAkB,CAAC;AACjC,cAAc,aAAa,CAAC;AAC5B,OAAO,EAAE,MAAM,IAAI,OAAO,EAAE,MAAM,aAAa,CAAC;AAChD,cAAc,kBAAkB,CAAC;AACjC,cAAc,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,CAAC,MAAM,CAAC;IACX,UAAU,WAAW;QAEjB,OAAO,EAAE,KAAK,CAAC;KAClB;IAED,UAAU,iBAAiB;QAEvB,OAAO,EAAE,KAAK,CAAC;KAClB;CACJ;AAED,cAAc,kBAAkB,CAAC;AACjC,cAAc,aAAa,CAAC;AAC5B,OAAO,EAAE,MAAM,IAAI,OAAO,EAAE,MAAM,aAAa,CAAC;AAChD,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,cAAc,YAAY,CAAC"}
package/esm/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  export * from "./basic/index.js";
2
2
  export * from "./struct.js";
3
3
  export { Struct as default } from "./struct.js";
4
+ export * from "./sync-promise.js";
4
5
  export * from "./types/index.js";
5
6
  export * from "./utils.js";
6
7
  //# sourceMappingURL=index.js.map