@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.
- package/CHANGELOG.json +21 -0
- package/CHANGELOG.md +11 -1
- package/README.md +126 -143
- package/esm/basic/definition.d.ts +3 -3
- package/esm/basic/definition.d.ts.map +1 -1
- package/esm/basic/definition.js.map +1 -1
- package/esm/basic/stream.d.ts +11 -6
- package/esm/basic/stream.d.ts.map +1 -1
- package/esm/basic/stream.js +7 -1
- package/esm/basic/stream.js.map +1 -1
- package/esm/index.d.ts +1 -0
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +1 -0
- package/esm/index.js.map +1 -1
- package/esm/struct.d.ts +19 -9
- package/esm/struct.d.ts.map +1 -1
- package/esm/struct.js +57 -25
- package/esm/struct.js.map +1 -1
- package/esm/sync-promise.js +12 -12
- package/esm/sync-promise.js.map +1 -1
- package/esm/types/bigint.d.ts +3 -3
- package/esm/types/bigint.d.ts.map +1 -1
- package/esm/types/bigint.js +1 -1
- package/esm/types/bigint.js.map +1 -1
- package/esm/types/buffer/base.d.ts +3 -3
- package/esm/types/buffer/base.d.ts.map +1 -1
- package/esm/types/buffer/base.js +1 -1
- package/esm/types/buffer/base.js.map +1 -1
- package/esm/types/number.d.ts +3 -3
- package/esm/types/number.d.ts.map +1 -1
- package/esm/types/number.js +14 -16
- package/esm/types/number.js.map +1 -1
- package/package.json +6 -6
- package/src/basic/definition.ts +3 -6
- package/src/basic/stream.ts +17 -6
- package/src/index.ts +1 -0
- package/src/struct.ts +79 -46
- package/src/sync-promise.ts +12 -12
- package/src/types/bigint.ts +6 -6
- package/src/types/buffer/base.ts +6 -6
- package/src/types/number.ts +23 -27
- 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
|
|
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.
|
|
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
|
|
27
|
+
import Struct from "@yume-chan/struct";
|
|
28
28
|
|
|
29
|
-
const MyStruct =
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
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:
|
|
45
|
+
baz: "Hello, World!",
|
|
47
46
|
});
|
|
48
47
|
```
|
|
49
48
|
|
|
50
49
|
<!-- cspell: disable -->
|
|
51
50
|
|
|
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
|
-
|
|
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`][
|
|
95
|
-
| [`ArrayBuffer`][
|
|
96
|
-
| [`Uint8Array`][
|
|
97
|
-
| [`DataView`][
|
|
98
|
-
|
|
|
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`][
|
|
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`][
|
|
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
|
-
[
|
|
117
|
-
[
|
|
118
|
-
[
|
|
119
|
-
[
|
|
120
|
-
[
|
|
121
|
-
[
|
|
122
|
-
[
|
|
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
|
-
|
|
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
|
-
|
|
189
|
+
|
|
190
|
+
</details><br/>
|
|
190
191
|
|
|
191
192
|
**Parameters**
|
|
192
193
|
|
|
193
194
|
1. `options`:
|
|
194
|
-
|
|
195
|
+
- `littleEndian:boolean = false`: Whether all multi-byte fields in this struct are [little-endian encoded][wikipeida_endianess].
|
|
195
196
|
|
|
196
|
-
[
|
|
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
|
-
|
|
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({
|
|
247
|
-
struct.serialize({ foo:
|
|
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
|
|
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(
|
|
261
|
-
.int32(
|
|
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
|
|
330
|
+
The `options` parameter defines its length, it supports two formats:
|
|
330
331
|
|
|
331
|
-
|
|
332
|
-
|
|
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
|
-
#### `
|
|
335
|
+
#### `concat`
|
|
335
336
|
|
|
336
337
|
```ts
|
|
337
|
-
|
|
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
|
-
|
|
432
|
-
|
|
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:
|
|
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
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
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(
|
|
520
|
-
.string(
|
|
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
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
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
|
-
|
|
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
|
|
544
|
+
* (due to end of file or other error condition), it must throw an {@link ExactReadableEndedError}.
|
|
557
545
|
*/
|
|
558
|
-
|
|
546
|
+
readExactly(length: number): Uint8Array;
|
|
559
547
|
}
|
|
560
548
|
|
|
561
|
-
interface
|
|
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
|
|
556
|
+
* (due to end of file or other error condition), it must throw an {@link ExactReadableEndedError}.
|
|
567
557
|
*/
|
|
568
|
-
|
|
558
|
+
readExactly(length: number): ValueOrPromise<Uint8Array>;
|
|
569
559
|
}
|
|
570
560
|
|
|
571
561
|
deserialize(
|
|
572
|
-
stream:
|
|
562
|
+
stream: ExactReadable,
|
|
573
563
|
): TPostDeserialized extends undefined
|
|
574
564
|
? Overwrite<TExtra, TValue>
|
|
575
565
|
: TPostDeserialized
|
|
576
566
|
>;
|
|
577
567
|
deserialize(
|
|
578
|
-
stream:
|
|
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(
|
|
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
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
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:
|
|
688
|
+
stream: ExactReadable,
|
|
706
689
|
struct: StructValue,
|
|
707
690
|
): StructFieldValue<this>;
|
|
708
691
|
abstract deserialize(
|
|
709
692
|
options: Readonly<StructOptions>,
|
|
710
|
-
stream:
|
|
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 {
|
|
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:
|
|
42
|
-
abstract deserialize(options: Readonly<StructOptions>, stream:
|
|
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,
|
|
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":"
|
|
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"}
|
package/esm/basic/stream.d.ts
CHANGED
|
@@ -1,20 +1,25 @@
|
|
|
1
1
|
import type { ValueOrPromise } from "../utils.js";
|
|
2
|
-
export
|
|
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
|
|
11
|
+
* (due to end of file or other error condition), it must throw an {@link ExactReadableEndedError}.
|
|
8
12
|
*/
|
|
9
|
-
|
|
13
|
+
readExactly(length: number): Uint8Array;
|
|
10
14
|
}
|
|
11
|
-
export interface
|
|
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
|
|
21
|
+
* (due to end of file or other error condition), it must throw an {@link ExactReadableEndedError}.
|
|
17
22
|
*/
|
|
18
|
-
|
|
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,
|
|
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"}
|
package/esm/basic/stream.js
CHANGED
|
@@ -1,2 +1,8 @@
|
|
|
1
|
-
|
|
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
|
package/esm/basic/stream.js.map
CHANGED
|
@@ -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
|
package/esm/index.d.ts.map
CHANGED
|
@@ -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