@yume-chan/struct 0.0.19 → 0.0.21
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 +27 -0
- package/CHANGELOG.md +16 -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/field-value.d.ts.map +1 -1
- package/esm/basic/field-value.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/basic/struct-value.d.ts.map +1 -1
- package/esm/basic/struct-value.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 -12
- package/esm/struct.d.ts.map +1 -1
- package/esm/struct.js +70 -38
- 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 +2 -3
- 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 +3 -5
- package/esm/types/buffer/base.js.map +1 -1
- package/esm/types/buffer/fixed-length.d.ts.map +1 -1
- package/esm/types/buffer/fixed-length.js.map +1 -1
- package/esm/types/buffer/variable-length.d.ts.map +1 -1
- package/esm/types/buffer/variable-length.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 +15 -17
- package/esm/types/number.js.map +1 -1
- package/package.json +8 -8
- package/src/basic/definition.ts +15 -18
- package/src/basic/field-value.ts +11 -11
- package/src/basic/stream.ts +17 -6
- package/src/basic/struct-value.ts +4 -4
- package/src/index.ts +1 -0
- package/src/struct.ts +166 -133
- package/src/sync-promise.ts +25 -25
- package/src/types/bigint.ts +33 -41
- package/src/types/buffer/base.ts +38 -38
- package/src/types/buffer/fixed-length.ts +4 -3
- package/src/types/buffer/variable-length.ts +22 -20
- package/src/types/number.ts +40 -44
- package/tsconfig.build.tsbuildinfo +1 -1
package/src/struct.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import type {
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
AsyncExactReadable,
|
|
3
|
+
ExactReadable,
|
|
4
4
|
StructFieldDefinition,
|
|
5
5
|
StructFieldValue,
|
|
6
6
|
StructOptions,
|
|
7
7
|
} from "./basic/index.js";
|
|
8
8
|
import {
|
|
9
|
+
ExactReadableEndedError,
|
|
9
10
|
STRUCT_VALUE_SYMBOL,
|
|
10
11
|
StructDefaultOptions,
|
|
11
12
|
StructValue,
|
|
@@ -30,9 +31,7 @@ import {
|
|
|
30
31
|
import type { Evaluate, Identity, Overwrite, ValueOrPromise } from "./utils.js";
|
|
31
32
|
|
|
32
33
|
export interface StructLike<TValue> {
|
|
33
|
-
deserialize(
|
|
34
|
-
stream: StructDeserializeStream | StructAsyncDeserializeStream
|
|
35
|
-
): Promise<TValue>;
|
|
34
|
+
deserialize(stream: ExactReadable | AsyncExactReadable): Promise<TValue>;
|
|
36
35
|
}
|
|
37
36
|
|
|
38
37
|
/**
|
|
@@ -51,7 +50,7 @@ type AddFieldDescriptor<
|
|
|
51
50
|
TExtra extends object,
|
|
52
51
|
TPostDeserialized,
|
|
53
52
|
TFieldName extends PropertyKey,
|
|
54
|
-
TDefinition extends StructFieldDefinition<any, any, any
|
|
53
|
+
TDefinition extends StructFieldDefinition<any, any, any>,
|
|
55
54
|
> = Identity<
|
|
56
55
|
Struct<
|
|
57
56
|
// Merge two types
|
|
@@ -71,7 +70,7 @@ interface ArrayBufferLikeFieldCreator<
|
|
|
71
70
|
TFields extends object,
|
|
72
71
|
TOmitInitKey extends PropertyKey,
|
|
73
72
|
TExtra extends object,
|
|
74
|
-
TPostDeserialized
|
|
73
|
+
TPostDeserialized,
|
|
75
74
|
> {
|
|
76
75
|
/**
|
|
77
76
|
* Append a fixed-length array buffer like field to the `Struct`
|
|
@@ -85,12 +84,12 @@ interface ArrayBufferLikeFieldCreator<
|
|
|
85
84
|
<
|
|
86
85
|
TName extends PropertyKey,
|
|
87
86
|
TType extends BufferFieldSubType<any, any>,
|
|
88
|
-
TTypeScriptType = TType["TTypeScriptType"]
|
|
87
|
+
TTypeScriptType = TType["TTypeScriptType"],
|
|
89
88
|
>(
|
|
90
89
|
name: TName,
|
|
91
90
|
type: TType,
|
|
92
91
|
options: FixedLengthBufferLikeFieldOptions,
|
|
93
|
-
typeScriptType?: TTypeScriptType
|
|
92
|
+
typeScriptType?: TTypeScriptType,
|
|
94
93
|
): AddFieldDescriptor<
|
|
95
94
|
TFields,
|
|
96
95
|
TOmitInitKey,
|
|
@@ -110,12 +109,12 @@ interface ArrayBufferLikeFieldCreator<
|
|
|
110
109
|
TName extends PropertyKey,
|
|
111
110
|
TType extends BufferFieldSubType<any, any>,
|
|
112
111
|
TOptions extends VariableLengthBufferLikeFieldOptions<TFields>,
|
|
113
|
-
TTypeScriptType = TType["TTypeScriptType"]
|
|
112
|
+
TTypeScriptType = TType["TTypeScriptType"],
|
|
114
113
|
>(
|
|
115
114
|
name: TName,
|
|
116
115
|
type: TType,
|
|
117
116
|
options: TOptions,
|
|
118
|
-
typeScriptType?: TTypeScriptType
|
|
117
|
+
typeScriptType?: TTypeScriptType,
|
|
119
118
|
): AddFieldDescriptor<
|
|
120
119
|
TFields,
|
|
121
120
|
TOmitInitKey,
|
|
@@ -134,12 +133,12 @@ interface BoundArrayBufferLikeFieldDefinitionCreator<
|
|
|
134
133
|
TOmitInitKey extends PropertyKey,
|
|
135
134
|
TExtra extends object,
|
|
136
135
|
TPostDeserialized,
|
|
137
|
-
TType extends BufferFieldSubType<any, any
|
|
136
|
+
TType extends BufferFieldSubType<any, any>,
|
|
138
137
|
> {
|
|
139
138
|
<TName extends PropertyKey, TTypeScriptType = TType["TTypeScriptType"]>(
|
|
140
139
|
name: TName,
|
|
141
140
|
options: FixedLengthBufferLikeFieldOptions,
|
|
142
|
-
typeScriptType?: TTypeScriptType
|
|
141
|
+
typeScriptType?: TTypeScriptType,
|
|
143
142
|
): AddFieldDescriptor<
|
|
144
143
|
TFields,
|
|
145
144
|
TOmitInitKey,
|
|
@@ -160,11 +159,11 @@ interface BoundArrayBufferLikeFieldDefinitionCreator<
|
|
|
160
159
|
TFields,
|
|
161
160
|
TLengthField
|
|
162
161
|
>,
|
|
163
|
-
TTypeScriptType = TType["TTypeScriptType"]
|
|
162
|
+
TTypeScriptType = TType["TTypeScriptType"],
|
|
164
163
|
>(
|
|
165
164
|
name: TName,
|
|
166
165
|
options: TOptions,
|
|
167
|
-
typeScriptType?: TTypeScriptType
|
|
166
|
+
typeScriptType?: TTypeScriptType,
|
|
168
167
|
): AddFieldDescriptor<
|
|
169
168
|
TFields,
|
|
170
169
|
TOmitInitKey,
|
|
@@ -181,73 +180,100 @@ interface BoundArrayBufferLikeFieldDefinitionCreator<
|
|
|
181
180
|
|
|
182
181
|
export type StructPostDeserialized<TFields, TPostDeserialized> = (
|
|
183
182
|
this: TFields,
|
|
184
|
-
object: TFields
|
|
183
|
+
object: TFields,
|
|
185
184
|
) => TPostDeserialized;
|
|
186
185
|
|
|
187
186
|
export type StructDeserializedResult<
|
|
188
187
|
TFields extends object,
|
|
189
188
|
TExtra extends object,
|
|
190
|
-
TPostDeserialized
|
|
189
|
+
TPostDeserialized,
|
|
191
190
|
> = TPostDeserialized extends undefined
|
|
192
191
|
? Overwrite<TExtra, TFields>
|
|
193
192
|
: TPostDeserialized;
|
|
194
193
|
|
|
194
|
+
export class StructDeserializeError extends Error {
|
|
195
|
+
constructor(message: string) {
|
|
196
|
+
super(message);
|
|
197
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
export class StructNotEnoughDataError extends StructDeserializeError {
|
|
202
|
+
constructor() {
|
|
203
|
+
super(
|
|
204
|
+
"The underlying readable was ended before the struct was fully deserialized",
|
|
205
|
+
);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
export class StructEmptyError extends StructDeserializeError {
|
|
210
|
+
constructor() {
|
|
211
|
+
super("The underlying readable doesn't contain any more struct");
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
195
215
|
export class Struct<
|
|
196
216
|
TFields extends object = Record<never, never>,
|
|
197
217
|
TOmitInitKey extends PropertyKey = never,
|
|
198
218
|
TExtra extends object = Record<never, never>,
|
|
199
|
-
TPostDeserialized = undefined
|
|
219
|
+
TPostDeserialized = undefined,
|
|
200
220
|
> implements
|
|
201
221
|
StructLike<
|
|
202
222
|
StructDeserializedResult<TFields, TExtra, TPostDeserialized>
|
|
203
223
|
>
|
|
204
224
|
{
|
|
205
|
-
|
|
225
|
+
readonly TFields!: TFields;
|
|
206
226
|
|
|
207
|
-
|
|
227
|
+
readonly TOmitInitKey!: TOmitInitKey;
|
|
208
228
|
|
|
209
|
-
|
|
229
|
+
readonly TExtra!: TExtra;
|
|
210
230
|
|
|
211
|
-
|
|
231
|
+
readonly TInit!: Evaluate<Omit<TFields, TOmitInitKey>>;
|
|
212
232
|
|
|
213
|
-
|
|
233
|
+
readonly TDeserializeResult!: StructDeserializedResult<
|
|
214
234
|
TFields,
|
|
215
235
|
TExtra,
|
|
216
236
|
TPostDeserialized
|
|
217
237
|
>;
|
|
218
238
|
|
|
219
|
-
|
|
239
|
+
readonly options: Readonly<StructOptions>;
|
|
220
240
|
|
|
221
|
-
|
|
241
|
+
#size = 0;
|
|
222
242
|
/**
|
|
223
243
|
* Gets the static size (exclude fields that can change size at runtime)
|
|
224
244
|
*/
|
|
225
|
-
|
|
226
|
-
return this
|
|
245
|
+
get size() {
|
|
246
|
+
return this.#size;
|
|
227
247
|
}
|
|
228
248
|
|
|
229
|
-
|
|
249
|
+
#fields: [
|
|
230
250
|
name: PropertyKey,
|
|
231
|
-
definition: StructFieldDefinition<any, any, any
|
|
251
|
+
definition: StructFieldDefinition<any, any, any>,
|
|
232
252
|
][] = [];
|
|
253
|
+
get fields(): readonly [
|
|
254
|
+
name: PropertyKey,
|
|
255
|
+
definition: StructFieldDefinition<any, any, any>,
|
|
256
|
+
][] {
|
|
257
|
+
return this.#fields;
|
|
258
|
+
}
|
|
233
259
|
|
|
234
|
-
|
|
260
|
+
#extra: Record<PropertyKey, unknown> = {};
|
|
235
261
|
|
|
236
|
-
|
|
262
|
+
#postDeserialized?: StructPostDeserialized<any, any> | undefined;
|
|
237
263
|
|
|
238
|
-
|
|
264
|
+
constructor(options?: Partial<Readonly<StructOptions>>) {
|
|
239
265
|
this.options = { ...StructDefaultOptions, ...options };
|
|
240
266
|
}
|
|
241
267
|
|
|
242
268
|
/**
|
|
243
269
|
* Appends a `StructFieldDefinition` to the `Struct
|
|
244
270
|
*/
|
|
245
|
-
|
|
271
|
+
field<
|
|
246
272
|
TName extends PropertyKey,
|
|
247
|
-
TDefinition extends StructFieldDefinition<any, any, any
|
|
273
|
+
TDefinition extends StructFieldDefinition<any, any, any>,
|
|
248
274
|
>(
|
|
249
275
|
name: TName,
|
|
250
|
-
definition: TDefinition
|
|
276
|
+
definition: TDefinition,
|
|
251
277
|
): AddFieldDescriptor<
|
|
252
278
|
TFields,
|
|
253
279
|
TOmitInitKey,
|
|
@@ -256,20 +282,20 @@ export class Struct<
|
|
|
256
282
|
TName,
|
|
257
283
|
TDefinition
|
|
258
284
|
> {
|
|
259
|
-
for (const field of this
|
|
285
|
+
for (const field of this.#fields) {
|
|
260
286
|
if (field[0] === name) {
|
|
287
|
+
// Convert Symbol to string
|
|
288
|
+
const nameString = String(name);
|
|
261
289
|
throw new Error(
|
|
262
|
-
`This struct already have a field with name '${
|
|
263
|
-
name
|
|
264
|
-
)}'`
|
|
290
|
+
`This struct already have a field with name '${nameString}'`,
|
|
265
291
|
);
|
|
266
292
|
}
|
|
267
293
|
}
|
|
268
294
|
|
|
269
|
-
this.
|
|
295
|
+
this.#fields.push([name, definition]);
|
|
270
296
|
|
|
271
297
|
const size = definition.getSize();
|
|
272
|
-
this
|
|
298
|
+
this.#size += size;
|
|
273
299
|
|
|
274
300
|
// Force cast `this` to another type
|
|
275
301
|
return this as any;
|
|
@@ -278,104 +304,104 @@ export class Struct<
|
|
|
278
304
|
/**
|
|
279
305
|
* Merges (flats) another `Struct`'s fields and extra fields into this one.
|
|
280
306
|
*/
|
|
281
|
-
|
|
282
|
-
other: TOther
|
|
307
|
+
concat<TOther extends Struct<any, any, any, any>>(
|
|
308
|
+
other: TOther,
|
|
283
309
|
): Struct<
|
|
284
310
|
TFields & TOther["TFields"],
|
|
285
311
|
TOmitInitKey | TOther["TOmitInitKey"],
|
|
286
312
|
TExtra & TOther["TExtra"],
|
|
287
313
|
TPostDeserialized
|
|
288
314
|
> {
|
|
289
|
-
for (const field of other
|
|
290
|
-
this.
|
|
315
|
+
for (const field of other.#fields) {
|
|
316
|
+
this.#fields.push(field);
|
|
291
317
|
}
|
|
292
|
-
this
|
|
318
|
+
this.#size += other.#size;
|
|
293
319
|
Object.defineProperties(
|
|
294
|
-
this
|
|
295
|
-
Object.getOwnPropertyDescriptors(other
|
|
320
|
+
this.#extra,
|
|
321
|
+
Object.getOwnPropertyDescriptors(other.#extra),
|
|
296
322
|
);
|
|
297
323
|
return this as any;
|
|
298
324
|
}
|
|
299
325
|
|
|
300
|
-
|
|
326
|
+
#number<
|
|
301
327
|
TName extends PropertyKey,
|
|
302
328
|
TType extends NumberFieldType = NumberFieldType,
|
|
303
|
-
TTypeScriptType = number
|
|
329
|
+
TTypeScriptType = number,
|
|
304
330
|
>(name: TName, type: TType, typeScriptType?: TTypeScriptType) {
|
|
305
331
|
return this.field(
|
|
306
332
|
name,
|
|
307
|
-
new NumberFieldDefinition(type, typeScriptType)
|
|
333
|
+
new NumberFieldDefinition(type, typeScriptType),
|
|
308
334
|
);
|
|
309
335
|
}
|
|
310
336
|
|
|
311
337
|
/**
|
|
312
338
|
* Appends an `int8` field to the `Struct`
|
|
313
339
|
*/
|
|
314
|
-
|
|
340
|
+
int8<TName extends PropertyKey, TTypeScriptType = number>(
|
|
315
341
|
name: TName,
|
|
316
|
-
typeScriptType?: TTypeScriptType
|
|
342
|
+
typeScriptType?: TTypeScriptType,
|
|
317
343
|
) {
|
|
318
|
-
return this
|
|
344
|
+
return this.#number(name, NumberFieldType.Int8, typeScriptType);
|
|
319
345
|
}
|
|
320
346
|
|
|
321
347
|
/**
|
|
322
348
|
* Appends an `uint8` field to the `Struct`
|
|
323
349
|
*/
|
|
324
|
-
|
|
350
|
+
uint8<TName extends PropertyKey, TTypeScriptType = number>(
|
|
325
351
|
name: TName,
|
|
326
|
-
typeScriptType?: TTypeScriptType
|
|
352
|
+
typeScriptType?: TTypeScriptType,
|
|
327
353
|
) {
|
|
328
|
-
return this
|
|
354
|
+
return this.#number(name, NumberFieldType.Uint8, typeScriptType);
|
|
329
355
|
}
|
|
330
356
|
|
|
331
357
|
/**
|
|
332
358
|
* Appends an `int16` field to the `Struct`
|
|
333
359
|
*/
|
|
334
|
-
|
|
360
|
+
int16<TName extends PropertyKey, TTypeScriptType = number>(
|
|
335
361
|
name: TName,
|
|
336
|
-
typeScriptType?: TTypeScriptType
|
|
362
|
+
typeScriptType?: TTypeScriptType,
|
|
337
363
|
) {
|
|
338
|
-
return this
|
|
364
|
+
return this.#number(name, NumberFieldType.Int16, typeScriptType);
|
|
339
365
|
}
|
|
340
366
|
|
|
341
367
|
/**
|
|
342
368
|
* Appends an `uint16` field to the `Struct`
|
|
343
369
|
*/
|
|
344
|
-
|
|
370
|
+
uint16<TName extends PropertyKey, TTypeScriptType = number>(
|
|
345
371
|
name: TName,
|
|
346
|
-
typeScriptType?: TTypeScriptType
|
|
372
|
+
typeScriptType?: TTypeScriptType,
|
|
347
373
|
) {
|
|
348
|
-
return this
|
|
374
|
+
return this.#number(name, NumberFieldType.Uint16, typeScriptType);
|
|
349
375
|
}
|
|
350
376
|
|
|
351
377
|
/**
|
|
352
378
|
* Appends an `int32` field to the `Struct`
|
|
353
379
|
*/
|
|
354
|
-
|
|
380
|
+
int32<TName extends PropertyKey, TTypeScriptType = number>(
|
|
355
381
|
name: TName,
|
|
356
|
-
typeScriptType?: TTypeScriptType
|
|
382
|
+
typeScriptType?: TTypeScriptType,
|
|
357
383
|
) {
|
|
358
|
-
return this
|
|
384
|
+
return this.#number(name, NumberFieldType.Int32, typeScriptType);
|
|
359
385
|
}
|
|
360
386
|
|
|
361
387
|
/**
|
|
362
388
|
* Appends an `uint32` field to the `Struct`
|
|
363
389
|
*/
|
|
364
|
-
|
|
390
|
+
uint32<TName extends PropertyKey, TTypeScriptType = number>(
|
|
365
391
|
name: TName,
|
|
366
|
-
typeScriptType?: TTypeScriptType
|
|
392
|
+
typeScriptType?: TTypeScriptType,
|
|
367
393
|
) {
|
|
368
|
-
return this
|
|
394
|
+
return this.#number(name, NumberFieldType.Uint32, typeScriptType);
|
|
369
395
|
}
|
|
370
396
|
|
|
371
|
-
|
|
397
|
+
#bigint<
|
|
372
398
|
TName extends PropertyKey,
|
|
373
399
|
TType extends BigIntFieldType = BigIntFieldType,
|
|
374
|
-
TTypeScriptType = TType["TTypeScriptType"]
|
|
400
|
+
TTypeScriptType = TType["TTypeScriptType"],
|
|
375
401
|
>(name: TName, type: TType, typeScriptType?: TTypeScriptType) {
|
|
376
402
|
return this.field(
|
|
377
403
|
name,
|
|
378
|
-
new BigIntFieldDefinition(type, typeScriptType)
|
|
404
|
+
new BigIntFieldDefinition(type, typeScriptType),
|
|
379
405
|
);
|
|
380
406
|
}
|
|
381
407
|
|
|
@@ -384,11 +410,11 @@ export class Struct<
|
|
|
384
410
|
*
|
|
385
411
|
* Requires native `BigInt` support
|
|
386
412
|
*/
|
|
387
|
-
|
|
413
|
+
int64<
|
|
388
414
|
TName extends PropertyKey,
|
|
389
|
-
TTypeScriptType = BigIntFieldType["TTypeScriptType"]
|
|
415
|
+
TTypeScriptType = BigIntFieldType["TTypeScriptType"],
|
|
390
416
|
>(name: TName, typeScriptType?: TTypeScriptType) {
|
|
391
|
-
return this
|
|
417
|
+
return this.#bigint(name, BigIntFieldType.Int64, typeScriptType);
|
|
392
418
|
}
|
|
393
419
|
|
|
394
420
|
/**
|
|
@@ -396,14 +422,14 @@ export class Struct<
|
|
|
396
422
|
*
|
|
397
423
|
* Requires native `BigInt` support
|
|
398
424
|
*/
|
|
399
|
-
|
|
425
|
+
uint64<
|
|
400
426
|
TName extends PropertyKey,
|
|
401
|
-
TTypeScriptType = BigIntFieldType["TTypeScriptType"]
|
|
427
|
+
TTypeScriptType = BigIntFieldType["TTypeScriptType"],
|
|
402
428
|
>(name: TName, typeScriptType?: TTypeScriptType) {
|
|
403
|
-
return this
|
|
429
|
+
return this.#bigint(name, BigIntFieldType.Uint64, typeScriptType);
|
|
404
430
|
}
|
|
405
431
|
|
|
406
|
-
|
|
432
|
+
#arrayBufferLike: ArrayBufferLikeFieldCreator<
|
|
407
433
|
TFields,
|
|
408
434
|
TOmitInitKey,
|
|
409
435
|
TExtra,
|
|
@@ -413,48 +439,48 @@ export class Struct<
|
|
|
413
439
|
type: BufferFieldSubType,
|
|
414
440
|
options:
|
|
415
441
|
| FixedLengthBufferLikeFieldOptions
|
|
416
|
-
| VariableLengthBufferLikeFieldOptions
|
|
442
|
+
| VariableLengthBufferLikeFieldOptions,
|
|
417
443
|
): any => {
|
|
418
444
|
if ("length" in options) {
|
|
419
445
|
return this.field(
|
|
420
446
|
name,
|
|
421
|
-
new FixedLengthBufferLikeFieldDefinition(type, options)
|
|
447
|
+
new FixedLengthBufferLikeFieldDefinition(type, options),
|
|
422
448
|
);
|
|
423
449
|
} else {
|
|
424
450
|
return this.field(
|
|
425
451
|
name,
|
|
426
|
-
new VariableLengthBufferLikeFieldDefinition(type, options)
|
|
452
|
+
new VariableLengthBufferLikeFieldDefinition(type, options),
|
|
427
453
|
);
|
|
428
454
|
}
|
|
429
455
|
};
|
|
430
456
|
|
|
431
|
-
|
|
457
|
+
uint8Array: BoundArrayBufferLikeFieldDefinitionCreator<
|
|
432
458
|
TFields,
|
|
433
459
|
TOmitInitKey,
|
|
434
460
|
TExtra,
|
|
435
461
|
TPostDeserialized,
|
|
436
462
|
Uint8ArrayBufferFieldSubType
|
|
437
463
|
> = (name: PropertyKey, options: any, typeScriptType: any): any => {
|
|
438
|
-
return this
|
|
464
|
+
return this.#arrayBufferLike(
|
|
439
465
|
name,
|
|
440
466
|
Uint8ArrayBufferFieldSubType.Instance,
|
|
441
467
|
options,
|
|
442
|
-
typeScriptType
|
|
468
|
+
typeScriptType,
|
|
443
469
|
);
|
|
444
470
|
};
|
|
445
471
|
|
|
446
|
-
|
|
472
|
+
string: BoundArrayBufferLikeFieldDefinitionCreator<
|
|
447
473
|
TFields,
|
|
448
474
|
TOmitInitKey,
|
|
449
475
|
TExtra,
|
|
450
476
|
TPostDeserialized,
|
|
451
477
|
StringBufferFieldSubType
|
|
452
478
|
> = (name: PropertyKey, options: any, typeScriptType: any): any => {
|
|
453
|
-
return this
|
|
479
|
+
return this.#arrayBufferLike(
|
|
454
480
|
name,
|
|
455
481
|
StringBufferFieldSubType.Instance,
|
|
456
482
|
options,
|
|
457
|
-
typeScriptType
|
|
483
|
+
typeScriptType,
|
|
458
484
|
);
|
|
459
485
|
};
|
|
460
486
|
|
|
@@ -468,18 +494,18 @@ export class Struct<
|
|
|
468
494
|
* @param value
|
|
469
495
|
* An object containing properties to be added to the result value. Accessors and methods are also allowed.
|
|
470
496
|
*/
|
|
471
|
-
|
|
497
|
+
extra<
|
|
472
498
|
T extends Record<
|
|
473
499
|
// This trick disallows any keys that are already in `TValue`
|
|
474
500
|
Exclude<keyof T, Exclude<keyof T, keyof TFields>>,
|
|
475
501
|
never
|
|
476
|
-
|
|
502
|
+
>,
|
|
477
503
|
>(
|
|
478
|
-
value: T & ThisType<Overwrite<Overwrite<TExtra, T>, TFields
|
|
504
|
+
value: T & ThisType<Overwrite<Overwrite<TExtra, T>, TFields>>,
|
|
479
505
|
): Struct<TFields, TOmitInitKey, Overwrite<TExtra, T>, TPostDeserialized> {
|
|
480
506
|
Object.defineProperties(
|
|
481
|
-
this
|
|
482
|
-
Object.getOwnPropertyDescriptors(value)
|
|
507
|
+
this.#extra,
|
|
508
|
+
Object.getOwnPropertyDescriptors(value),
|
|
483
509
|
);
|
|
484
510
|
return this as any;
|
|
485
511
|
}
|
|
@@ -490,8 +516,8 @@ export class Struct<
|
|
|
490
516
|
* A callback returning `never` (always throw an error)
|
|
491
517
|
* will also change the return type of `deserialize` to `never`.
|
|
492
518
|
*/
|
|
493
|
-
|
|
494
|
-
callback: StructPostDeserialized<TFields, never
|
|
519
|
+
postDeserialize(
|
|
520
|
+
callback: StructPostDeserialized<TFields, never>,
|
|
495
521
|
): Struct<TFields, TOmitInitKey, TExtra, never>;
|
|
496
522
|
/**
|
|
497
523
|
* Registers (or replaces) a custom callback to be run after deserialized.
|
|
@@ -499,8 +525,8 @@ export class Struct<
|
|
|
499
525
|
* A callback returning `void` means it modify the result object in-place
|
|
500
526
|
* (or doesn't modify it at all), so `deserialize` will still return the result object.
|
|
501
527
|
*/
|
|
502
|
-
|
|
503
|
-
callback?: StructPostDeserialized<TFields, void
|
|
528
|
+
postDeserialize(
|
|
529
|
+
callback?: StructPostDeserialized<TFields, void>,
|
|
504
530
|
): Struct<TFields, TOmitInitKey, TExtra, undefined>;
|
|
505
531
|
/**
|
|
506
532
|
* Registers (or replaces) a custom callback to be run after deserialized.
|
|
@@ -508,56 +534,63 @@ export class Struct<
|
|
|
508
534
|
* A callback returning anything other than `undefined`
|
|
509
535
|
* will `deserialize` to return that object instead.
|
|
510
536
|
*/
|
|
511
|
-
|
|
512
|
-
callback?: StructPostDeserialized<TFields, TPostSerialize
|
|
537
|
+
postDeserialize<TPostSerialize>(
|
|
538
|
+
callback?: StructPostDeserialized<TFields, TPostSerialize>,
|
|
513
539
|
): Struct<TFields, TOmitInitKey, TExtra, TPostSerialize>;
|
|
514
|
-
|
|
515
|
-
this
|
|
540
|
+
postDeserialize(callback?: StructPostDeserialized<TFields, any>) {
|
|
541
|
+
this.#postDeserialized = callback;
|
|
516
542
|
return this as any;
|
|
517
543
|
}
|
|
518
544
|
|
|
519
545
|
/**
|
|
520
546
|
* Deserialize a struct value from `stream`.
|
|
521
547
|
*/
|
|
522
|
-
|
|
523
|
-
stream:
|
|
548
|
+
deserialize(
|
|
549
|
+
stream: ExactReadable,
|
|
524
550
|
): StructDeserializedResult<TFields, TExtra, TPostDeserialized>;
|
|
525
|
-
|
|
526
|
-
stream:
|
|
551
|
+
deserialize(
|
|
552
|
+
stream: AsyncExactReadable,
|
|
527
553
|
): Promise<StructDeserializedResult<TFields, TExtra, TPostDeserialized>>;
|
|
528
|
-
|
|
529
|
-
stream:
|
|
554
|
+
deserialize(
|
|
555
|
+
stream: ExactReadable | AsyncExactReadable,
|
|
530
556
|
): ValueOrPromise<
|
|
531
557
|
StructDeserializedResult<TFields, TExtra, TPostDeserialized>
|
|
532
558
|
> {
|
|
533
|
-
const structValue = new StructValue(this
|
|
559
|
+
const structValue = new StructValue(this.#extra);
|
|
534
560
|
|
|
535
561
|
let promise = SyncPromise.resolve();
|
|
536
562
|
|
|
537
|
-
|
|
563
|
+
const startPosition = stream.position;
|
|
564
|
+
for (const [name, definition] of this.#fields) {
|
|
538
565
|
promise = promise
|
|
539
566
|
.then(() =>
|
|
540
|
-
definition.deserialize(
|
|
541
|
-
this.options,
|
|
542
|
-
stream as any,
|
|
543
|
-
structValue
|
|
544
|
-
)
|
|
567
|
+
definition.deserialize(this.options, stream, structValue),
|
|
545
568
|
)
|
|
546
|
-
.then(
|
|
547
|
-
|
|
548
|
-
|
|
569
|
+
.then(
|
|
570
|
+
(fieldValue) => {
|
|
571
|
+
structValue.set(name, fieldValue);
|
|
572
|
+
},
|
|
573
|
+
(e) => {
|
|
574
|
+
if (!(e instanceof ExactReadableEndedError)) {
|
|
575
|
+
throw e;
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
if (stream.position === startPosition) {
|
|
579
|
+
throw new StructEmptyError();
|
|
580
|
+
} else {
|
|
581
|
+
throw new StructNotEnoughDataError();
|
|
582
|
+
}
|
|
583
|
+
},
|
|
584
|
+
);
|
|
549
585
|
}
|
|
550
586
|
|
|
551
587
|
return promise
|
|
552
588
|
.then(() => {
|
|
553
|
-
const
|
|
589
|
+
const value = structValue.value;
|
|
554
590
|
|
|
555
591
|
// Run `postDeserialized`
|
|
556
|
-
if (this
|
|
557
|
-
const override = this.
|
|
558
|
-
object,
|
|
559
|
-
object
|
|
560
|
-
);
|
|
592
|
+
if (this.#postDeserialized) {
|
|
593
|
+
const override = this.#postDeserialized.call(value, value);
|
|
561
594
|
// If it returns a new value, use that as result
|
|
562
595
|
// Otherwise it only inspects/mutates the object in place.
|
|
563
596
|
if (override !== undefined) {
|
|
@@ -565,19 +598,19 @@ export class Struct<
|
|
|
565
598
|
}
|
|
566
599
|
}
|
|
567
600
|
|
|
568
|
-
return
|
|
601
|
+
return value;
|
|
569
602
|
})
|
|
570
603
|
.valueOrPromise();
|
|
571
604
|
}
|
|
572
605
|
|
|
573
|
-
|
|
574
|
-
|
|
606
|
+
serialize(init: Evaluate<Omit<TFields, TOmitInitKey>>): Uint8Array;
|
|
607
|
+
serialize(
|
|
575
608
|
init: Evaluate<Omit<TFields, TOmitInitKey>>,
|
|
576
|
-
output: Uint8Array
|
|
609
|
+
output: Uint8Array,
|
|
577
610
|
): number;
|
|
578
|
-
|
|
611
|
+
serialize(
|
|
579
612
|
init: Evaluate<Omit<TFields, TOmitInitKey>>,
|
|
580
|
-
output?: Uint8Array
|
|
613
|
+
output?: Uint8Array,
|
|
581
614
|
): Uint8Array | number {
|
|
582
615
|
let structValue: StructValue;
|
|
583
616
|
if (STRUCT_VALUE_SYMBOL in init) {
|
|
@@ -590,11 +623,11 @@ export class Struct<
|
|
|
590
623
|
}
|
|
591
624
|
} else {
|
|
592
625
|
structValue = new StructValue({});
|
|
593
|
-
for (const [name, definition] of this
|
|
626
|
+
for (const [name, definition] of this.#fields) {
|
|
594
627
|
const fieldValue = definition.create(
|
|
595
628
|
this.options,
|
|
596
629
|
structValue,
|
|
597
|
-
(init as any)[name]
|
|
630
|
+
(init as any)[name],
|
|
598
631
|
);
|
|
599
632
|
structValue.set(name, fieldValue);
|
|
600
633
|
}
|
|
@@ -603,7 +636,7 @@ export class Struct<
|
|
|
603
636
|
let structSize = 0;
|
|
604
637
|
const fieldsInfo: { fieldValue: StructFieldValue; size: number }[] = [];
|
|
605
638
|
|
|
606
|
-
for (const [name] of this
|
|
639
|
+
for (const [name] of this.#fields) {
|
|
607
640
|
const fieldValue = structValue.get(name);
|
|
608
641
|
const size = fieldValue.getSize();
|
|
609
642
|
fieldsInfo.push({ fieldValue, size });
|
|
@@ -619,7 +652,7 @@ export class Struct<
|
|
|
619
652
|
const dataView = new DataView(
|
|
620
653
|
output.buffer,
|
|
621
654
|
output.byteOffset,
|
|
622
|
-
output.byteLength
|
|
655
|
+
output.byteLength,
|
|
623
656
|
);
|
|
624
657
|
let offset = 0;
|
|
625
658
|
for (const { fieldValue, size } of fieldsInfo) {
|