@yume-chan/struct 0.0.18 → 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 +27 -0
- package/CHANGELOG.md +16 -1
- package/README.md +126 -143
- package/esm/basic/definition.d.ts +43 -43
- package/esm/basic/definition.d.ts.map +1 -1
- package/esm/basic/definition.js +23 -23
- package/esm/basic/definition.js.map +1 -1
- package/esm/basic/field-value.d.ts +38 -38
- package/esm/basic/field-value.d.ts.map +1 -1
- package/esm/basic/field-value.js +45 -45
- package/esm/basic/index.d.ts +5 -5
- package/esm/basic/index.js +5 -5
- package/esm/basic/options.d.ts +9 -9
- package/esm/basic/options.js +3 -3
- package/esm/basic/stream.d.ts +24 -19
- 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 +25 -25
- package/esm/basic/struct-value.d.ts.map +1 -1
- package/esm/basic/struct-value.js +56 -56
- package/esm/index.d.ts +14 -13
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +6 -5
- package/esm/index.js.map +1 -1
- package/esm/struct.d.ts +140 -129
- package/esm/struct.d.ts.map +1 -1
- package/esm/struct.js +242 -210
- package/esm/struct.js.map +1 -1
- package/esm/sync-promise.d.ts +12 -12
- package/esm/sync-promise.js +70 -70
- package/esm/sync-promise.js.map +1 -1
- package/esm/types/bigint.d.ts +25 -24
- package/esm/types/bigint.d.ts.map +1 -1
- package/esm/types/bigint.js +47 -46
- package/esm/types/bigint.js.map +1 -1
- package/esm/types/buffer/base.d.ts +64 -63
- package/esm/types/buffer/base.d.ts.map +1 -1
- package/esm/types/buffer/base.js +102 -100
- package/esm/types/buffer/base.js.map +1 -1
- package/esm/types/buffer/fixed-length.d.ts +8 -7
- package/esm/types/buffer/fixed-length.d.ts.map +1 -1
- package/esm/types/buffer/fixed-length.js +6 -6
- package/esm/types/buffer/fixed-length.js.map +1 -1
- package/esm/types/buffer/index.d.ts +3 -3
- package/esm/types/buffer/index.js +3 -3
- package/esm/types/buffer/variable-length.d.ts +44 -42
- package/esm/types/buffer/variable-length.d.ts.map +1 -1
- package/esm/types/buffer/variable-length.js +75 -75
- package/esm/types/buffer/variable-length.js.map +1 -1
- package/esm/types/index.d.ts +3 -3
- package/esm/types/index.js +3 -3
- package/esm/types/number.d.ts +27 -26
- package/esm/types/number.d.ts.map +1 -1
- package/esm/types/number.js +111 -113
- package/esm/types/number.js.map +1 -1
- package/esm/utils.d.ts +47 -47
- package/esm/utils.js +15 -15
- package/package.json +9 -8
- package/src/basic/definition.ts +6 -9
- package/src/basic/field-value.ts +3 -3
- package/src/basic/index.ts +5 -5
- package/src/basic/stream.ts +18 -7
- package/src/basic/struct-value.ts +1 -1
- package/src/index.ts +6 -5
- package/src/struct.ts +91 -59
- package/src/sync-promise.ts +12 -12
- package/src/types/bigint.ts +11 -12
- package/src/types/buffer/base.ts +12 -12
- package/src/types/buffer/fixed-length.ts +2 -1
- package/src/types/buffer/variable-length.ts +8 -11
- package/src/types/number.ts +28 -33
- package/tsconfig.build.tsbuildinfo +1 -1
package/src/struct.ts
CHANGED
|
@@ -1,14 +1,23 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
AsyncExactReadable,
|
|
3
|
+
ExactReadable,
|
|
4
|
+
StructFieldDefinition,
|
|
5
|
+
StructFieldValue,
|
|
6
|
+
StructOptions,
|
|
7
|
+
} from "./basic/index.js";
|
|
1
8
|
import {
|
|
9
|
+
ExactReadableEndedError,
|
|
2
10
|
STRUCT_VALUE_SYMBOL,
|
|
3
11
|
StructDefaultOptions,
|
|
4
12
|
StructValue,
|
|
5
|
-
type StructAsyncDeserializeStream,
|
|
6
|
-
type StructDeserializeStream,
|
|
7
|
-
type StructFieldDefinition,
|
|
8
|
-
type StructFieldValue,
|
|
9
|
-
type StructOptions,
|
|
10
13
|
} from "./basic/index.js";
|
|
11
14
|
import { SyncPromise } from "./sync-promise.js";
|
|
15
|
+
import type {
|
|
16
|
+
BufferFieldSubType,
|
|
17
|
+
FixedLengthBufferLikeFieldOptions,
|
|
18
|
+
LengthField,
|
|
19
|
+
VariableLengthBufferLikeFieldOptions,
|
|
20
|
+
} from "./types/index.js";
|
|
12
21
|
import {
|
|
13
22
|
BigIntFieldDefinition,
|
|
14
23
|
BigIntFieldType,
|
|
@@ -18,22 +27,11 @@ import {
|
|
|
18
27
|
StringBufferFieldSubType,
|
|
19
28
|
Uint8ArrayBufferFieldSubType,
|
|
20
29
|
VariableLengthBufferLikeFieldDefinition,
|
|
21
|
-
type BufferFieldSubType,
|
|
22
|
-
type FixedLengthBufferLikeFieldOptions,
|
|
23
|
-
type LengthField,
|
|
24
|
-
type VariableLengthBufferLikeFieldOptions,
|
|
25
30
|
} from "./types/index.js";
|
|
26
|
-
import {
|
|
27
|
-
type Evaluate,
|
|
28
|
-
type Identity,
|
|
29
|
-
type Overwrite,
|
|
30
|
-
type ValueOrPromise,
|
|
31
|
-
} from "./utils.js";
|
|
31
|
+
import type { Evaluate, Identity, Overwrite, ValueOrPromise } from "./utils.js";
|
|
32
32
|
|
|
33
33
|
export interface StructLike<TValue> {
|
|
34
|
-
deserialize(
|
|
35
|
-
stream: StructDeserializeStream | StructAsyncDeserializeStream
|
|
36
|
-
): Promise<TValue>;
|
|
34
|
+
deserialize(stream: ExactReadable | AsyncExactReadable): Promise<TValue>;
|
|
37
35
|
}
|
|
38
36
|
|
|
39
37
|
/**
|
|
@@ -193,6 +191,27 @@ export type StructDeserializedResult<
|
|
|
193
191
|
? Overwrite<TExtra, TFields>
|
|
194
192
|
: TPostDeserialized;
|
|
195
193
|
|
|
194
|
+
export class StructDeserializeError extends Error {
|
|
195
|
+
public constructor(message: string) {
|
|
196
|
+
super(message);
|
|
197
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
export class StructNotEnoughDataError extends StructDeserializeError {
|
|
202
|
+
public 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
|
+
public constructor() {
|
|
211
|
+
super("The underlying readable doesn't contain any more struct");
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
196
215
|
export class Struct<
|
|
197
216
|
TFields extends object = Record<never, never>,
|
|
198
217
|
TOmitInitKey extends PropertyKey = never,
|
|
@@ -219,22 +238,28 @@ export class Struct<
|
|
|
219
238
|
|
|
220
239
|
public readonly options: Readonly<StructOptions>;
|
|
221
240
|
|
|
222
|
-
|
|
241
|
+
#size = 0;
|
|
223
242
|
/**
|
|
224
243
|
* Gets the static size (exclude fields that can change size at runtime)
|
|
225
244
|
*/
|
|
226
245
|
public get size() {
|
|
227
|
-
return this
|
|
246
|
+
return this.#size;
|
|
228
247
|
}
|
|
229
248
|
|
|
230
|
-
|
|
249
|
+
#fields: [
|
|
231
250
|
name: PropertyKey,
|
|
232
251
|
definition: StructFieldDefinition<any, any, any>
|
|
233
252
|
][] = [];
|
|
253
|
+
public get fields(): readonly [
|
|
254
|
+
name: PropertyKey,
|
|
255
|
+
definition: StructFieldDefinition<any, any, any>
|
|
256
|
+
][] {
|
|
257
|
+
return this.#fields;
|
|
258
|
+
}
|
|
234
259
|
|
|
235
|
-
|
|
260
|
+
#extra: Record<PropertyKey, unknown> = {};
|
|
236
261
|
|
|
237
|
-
|
|
262
|
+
#postDeserialized?: StructPostDeserialized<any, any> | undefined;
|
|
238
263
|
|
|
239
264
|
public constructor(options?: Partial<Readonly<StructOptions>>) {
|
|
240
265
|
this.options = { ...StructDefaultOptions, ...options };
|
|
@@ -257,20 +282,20 @@ export class Struct<
|
|
|
257
282
|
TName,
|
|
258
283
|
TDefinition
|
|
259
284
|
> {
|
|
260
|
-
for (const field of this
|
|
285
|
+
for (const field of this.#fields) {
|
|
261
286
|
if (field[0] === name) {
|
|
287
|
+
// Convert Symbol to string
|
|
288
|
+
const nameString = String(name);
|
|
262
289
|
throw new Error(
|
|
263
|
-
`This struct already have a field with name '${
|
|
264
|
-
name
|
|
265
|
-
)}'`
|
|
290
|
+
`This struct already have a field with name '${nameString}'`
|
|
266
291
|
);
|
|
267
292
|
}
|
|
268
293
|
}
|
|
269
294
|
|
|
270
|
-
this.
|
|
295
|
+
this.#fields.push([name, definition]);
|
|
271
296
|
|
|
272
297
|
const size = definition.getSize();
|
|
273
|
-
this
|
|
298
|
+
this.#size += size;
|
|
274
299
|
|
|
275
300
|
// Force cast `this` to another type
|
|
276
301
|
return this as any;
|
|
@@ -279,7 +304,7 @@ export class Struct<
|
|
|
279
304
|
/**
|
|
280
305
|
* Merges (flats) another `Struct`'s fields and extra fields into this one.
|
|
281
306
|
*/
|
|
282
|
-
public
|
|
307
|
+
public concat<TOther extends Struct<any, any, any, any>>(
|
|
283
308
|
other: TOther
|
|
284
309
|
): Struct<
|
|
285
310
|
TFields & TOther["TFields"],
|
|
@@ -287,13 +312,13 @@ export class Struct<
|
|
|
287
312
|
TExtra & TOther["TExtra"],
|
|
288
313
|
TPostDeserialized
|
|
289
314
|
> {
|
|
290
|
-
for (const field of other
|
|
291
|
-
this.
|
|
315
|
+
for (const field of other.#fields) {
|
|
316
|
+
this.#fields.push(field);
|
|
292
317
|
}
|
|
293
|
-
this
|
|
318
|
+
this.#size += other.#size;
|
|
294
319
|
Object.defineProperties(
|
|
295
|
-
this
|
|
296
|
-
Object.getOwnPropertyDescriptors(other
|
|
320
|
+
this.#extra,
|
|
321
|
+
Object.getOwnPropertyDescriptors(other.#extra)
|
|
297
322
|
);
|
|
298
323
|
return this as any;
|
|
299
324
|
}
|
|
@@ -479,7 +504,7 @@ export class Struct<
|
|
|
479
504
|
value: T & ThisType<Overwrite<Overwrite<TExtra, T>, TFields>>
|
|
480
505
|
): Struct<TFields, TOmitInitKey, Overwrite<TExtra, T>, TPostDeserialized> {
|
|
481
506
|
Object.defineProperties(
|
|
482
|
-
this
|
|
507
|
+
this.#extra,
|
|
483
508
|
Object.getOwnPropertyDescriptors(value)
|
|
484
509
|
);
|
|
485
510
|
return this as any;
|
|
@@ -513,7 +538,7 @@ export class Struct<
|
|
|
513
538
|
callback?: StructPostDeserialized<TFields, TPostSerialize>
|
|
514
539
|
): Struct<TFields, TOmitInitKey, TExtra, TPostSerialize>;
|
|
515
540
|
public postDeserialize(callback?: StructPostDeserialized<TFields, any>) {
|
|
516
|
-
this
|
|
541
|
+
this.#postDeserialized = callback;
|
|
517
542
|
return this as any;
|
|
518
543
|
}
|
|
519
544
|
|
|
@@ -521,44 +546,51 @@ export class Struct<
|
|
|
521
546
|
* Deserialize a struct value from `stream`.
|
|
522
547
|
*/
|
|
523
548
|
public deserialize(
|
|
524
|
-
stream:
|
|
549
|
+
stream: ExactReadable
|
|
525
550
|
): StructDeserializedResult<TFields, TExtra, TPostDeserialized>;
|
|
526
551
|
public deserialize(
|
|
527
|
-
stream:
|
|
552
|
+
stream: AsyncExactReadable
|
|
528
553
|
): Promise<StructDeserializedResult<TFields, TExtra, TPostDeserialized>>;
|
|
529
554
|
public deserialize(
|
|
530
|
-
stream:
|
|
555
|
+
stream: ExactReadable | AsyncExactReadable
|
|
531
556
|
): ValueOrPromise<
|
|
532
557
|
StructDeserializedResult<TFields, TExtra, TPostDeserialized>
|
|
533
558
|
> {
|
|
534
|
-
const structValue = new StructValue(this
|
|
559
|
+
const structValue = new StructValue(this.#extra);
|
|
535
560
|
|
|
536
561
|
let promise = SyncPromise.resolve();
|
|
537
562
|
|
|
538
|
-
|
|
563
|
+
const startPosition = stream.position;
|
|
564
|
+
for (const [name, definition] of this.#fields) {
|
|
539
565
|
promise = promise
|
|
540
566
|
.then(() =>
|
|
541
|
-
definition.deserialize(
|
|
542
|
-
this.options,
|
|
543
|
-
stream as any,
|
|
544
|
-
structValue
|
|
545
|
-
)
|
|
567
|
+
definition.deserialize(this.options, stream, structValue)
|
|
546
568
|
)
|
|
547
|
-
.then(
|
|
548
|
-
|
|
549
|
-
|
|
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
|
+
);
|
|
550
585
|
}
|
|
551
586
|
|
|
552
587
|
return promise
|
|
553
588
|
.then(() => {
|
|
554
|
-
const
|
|
589
|
+
const value = structValue.value;
|
|
555
590
|
|
|
556
591
|
// Run `postDeserialized`
|
|
557
|
-
if (this
|
|
558
|
-
const override = this.
|
|
559
|
-
object,
|
|
560
|
-
object
|
|
561
|
-
);
|
|
592
|
+
if (this.#postDeserialized) {
|
|
593
|
+
const override = this.#postDeserialized.call(value, value);
|
|
562
594
|
// If it returns a new value, use that as result
|
|
563
595
|
// Otherwise it only inspects/mutates the object in place.
|
|
564
596
|
if (override !== undefined) {
|
|
@@ -566,7 +598,7 @@ export class Struct<
|
|
|
566
598
|
}
|
|
567
599
|
}
|
|
568
600
|
|
|
569
|
-
return
|
|
601
|
+
return value;
|
|
570
602
|
})
|
|
571
603
|
.valueOrPromise();
|
|
572
604
|
}
|
|
@@ -591,7 +623,7 @@ export class Struct<
|
|
|
591
623
|
}
|
|
592
624
|
} else {
|
|
593
625
|
structValue = new StructValue({});
|
|
594
|
-
for (const [name, definition] of this
|
|
626
|
+
for (const [name, definition] of this.#fields) {
|
|
595
627
|
const fieldValue = definition.create(
|
|
596
628
|
this.options,
|
|
597
629
|
structValue,
|
|
@@ -604,7 +636,7 @@ export class Struct<
|
|
|
604
636
|
let structSize = 0;
|
|
605
637
|
const fieldsInfo: { fieldValue: StructFieldValue; size: number }[] = [];
|
|
606
638
|
|
|
607
|
-
for (const [name] of this
|
|
639
|
+
for (const [name] of this.#fields) {
|
|
608
640
|
const fieldValue = structValue.get(name);
|
|
609
641
|
const size = fieldValue.getSize();
|
|
610
642
|
fieldsInfo.push({ fieldValue, size });
|
package/src/sync-promise.ts
CHANGED
|
@@ -55,10 +55,10 @@ export const SyncPromise: SyncPromiseStatic = {
|
|
|
55
55
|
};
|
|
56
56
|
|
|
57
57
|
class PendingSyncPromise<T> implements SyncPromise<T> {
|
|
58
|
-
|
|
58
|
+
#promise: PromiseLike<T>;
|
|
59
59
|
|
|
60
60
|
public constructor(promise: PromiseLike<T>) {
|
|
61
|
-
this
|
|
61
|
+
this.#promise = promise;
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
public then<TResult1 = T, TResult2 = never>(
|
|
@@ -72,20 +72,20 @@ class PendingSyncPromise<T> implements SyncPromise<T> {
|
|
|
72
72
|
| undefined
|
|
73
73
|
) {
|
|
74
74
|
return new PendingSyncPromise<TResult1 | TResult2>(
|
|
75
|
-
this
|
|
75
|
+
this.#promise.then(onfulfilled, onrejected)
|
|
76
76
|
);
|
|
77
77
|
}
|
|
78
78
|
|
|
79
79
|
public valueOrPromise(): T | PromiseLike<T> {
|
|
80
|
-
return this
|
|
80
|
+
return this.#promise;
|
|
81
81
|
}
|
|
82
82
|
}
|
|
83
83
|
|
|
84
84
|
class ResolvedSyncPromise<T> implements SyncPromise<T> {
|
|
85
|
-
|
|
85
|
+
#value: T;
|
|
86
86
|
|
|
87
87
|
public constructor(value: T) {
|
|
88
|
-
this
|
|
88
|
+
this.#value = value;
|
|
89
89
|
}
|
|
90
90
|
|
|
91
91
|
public then<TResult1 = T>(
|
|
@@ -97,19 +97,19 @@ class ResolvedSyncPromise<T> implements SyncPromise<T> {
|
|
|
97
97
|
if (!onfulfilled) {
|
|
98
98
|
return this as any;
|
|
99
99
|
}
|
|
100
|
-
return SyncPromise.try(() => onfulfilled(this
|
|
100
|
+
return SyncPromise.try(() => onfulfilled(this.#value));
|
|
101
101
|
}
|
|
102
102
|
|
|
103
103
|
public valueOrPromise(): T | PromiseLike<T> {
|
|
104
|
-
return this
|
|
104
|
+
return this.#value;
|
|
105
105
|
}
|
|
106
106
|
}
|
|
107
107
|
|
|
108
108
|
class RejectedSyncPromise<T> implements SyncPromise<T> {
|
|
109
|
-
|
|
109
|
+
#reason: any;
|
|
110
110
|
|
|
111
111
|
public constructor(reason: any) {
|
|
112
|
-
this
|
|
112
|
+
this.#reason = reason;
|
|
113
113
|
}
|
|
114
114
|
|
|
115
115
|
public then<TResult1 = T, TResult2 = never>(
|
|
@@ -125,10 +125,10 @@ class RejectedSyncPromise<T> implements SyncPromise<T> {
|
|
|
125
125
|
if (!onrejected) {
|
|
126
126
|
return this as any;
|
|
127
127
|
}
|
|
128
|
-
return SyncPromise.try(() => onrejected(this
|
|
128
|
+
return SyncPromise.try(() => onrejected(this.#reason));
|
|
129
129
|
}
|
|
130
130
|
|
|
131
131
|
public valueOrPromise(): T | PromiseLike<T> {
|
|
132
|
-
throw this
|
|
132
|
+
throw this.#reason;
|
|
133
133
|
}
|
|
134
134
|
}
|
package/src/types/bigint.ts
CHANGED
|
@@ -5,16 +5,15 @@ import {
|
|
|
5
5
|
setBigUint64,
|
|
6
6
|
} from "@yume-chan/dataview-bigint-polyfill/esm/fallback.js";
|
|
7
7
|
|
|
8
|
-
import {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
type StructOptions,
|
|
14
|
-
type StructValue,
|
|
8
|
+
import type {
|
|
9
|
+
AsyncExactReadable,
|
|
10
|
+
ExactReadable,
|
|
11
|
+
StructOptions,
|
|
12
|
+
StructValue,
|
|
15
13
|
} from "../basic/index.js";
|
|
14
|
+
import { StructFieldDefinition, StructFieldValue } from "../basic/index.js";
|
|
16
15
|
import { SyncPromise } from "../sync-promise.js";
|
|
17
|
-
import {
|
|
16
|
+
import type { ValueOrPromise } from "../utils.js";
|
|
18
17
|
|
|
19
18
|
type DataViewBigInt64Getter = (
|
|
20
19
|
dataView: DataView,
|
|
@@ -87,21 +86,21 @@ export class BigIntFieldDefinition<
|
|
|
87
86
|
|
|
88
87
|
public override deserialize(
|
|
89
88
|
options: Readonly<StructOptions>,
|
|
90
|
-
stream:
|
|
89
|
+
stream: ExactReadable,
|
|
91
90
|
struct: StructValue
|
|
92
91
|
): BigIntFieldValue<this>;
|
|
93
92
|
public override deserialize(
|
|
94
93
|
options: Readonly<StructOptions>,
|
|
95
|
-
stream:
|
|
94
|
+
stream: AsyncExactReadable,
|
|
96
95
|
struct: StructValue
|
|
97
96
|
): Promise<BigIntFieldValue<this>>;
|
|
98
97
|
public override deserialize(
|
|
99
98
|
options: Readonly<StructOptions>,
|
|
100
|
-
stream:
|
|
99
|
+
stream: ExactReadable | AsyncExactReadable,
|
|
101
100
|
struct: StructValue
|
|
102
101
|
): ValueOrPromise<BigIntFieldValue<this>> {
|
|
103
102
|
return SyncPromise.try(() => {
|
|
104
|
-
return stream.
|
|
103
|
+
return stream.readExactly(this.getSize());
|
|
105
104
|
})
|
|
106
105
|
.then((array) => {
|
|
107
106
|
const view = new DataView(
|
package/src/types/buffer/base.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
type StructOptions,
|
|
7
|
-
type StructValue,
|
|
1
|
+
import type {
|
|
2
|
+
AsyncExactReadable,
|
|
3
|
+
ExactReadable,
|
|
4
|
+
StructOptions,
|
|
5
|
+
StructValue,
|
|
8
6
|
} from "../../basic/index.js";
|
|
7
|
+
import { StructFieldDefinition, StructFieldValue } from "../../basic/index.js";
|
|
9
8
|
import { SyncPromise } from "../../sync-promise.js";
|
|
10
|
-
import {
|
|
9
|
+
import type { ValueOrPromise } from "../../utils.js";
|
|
10
|
+
import { decodeUtf8, encodeUtf8 } from "../../utils.js";
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* Base class for all types that
|
|
@@ -127,17 +127,17 @@ export abstract class BufferLikeFieldDefinition<
|
|
|
127
127
|
|
|
128
128
|
public override deserialize(
|
|
129
129
|
options: Readonly<StructOptions>,
|
|
130
|
-
stream:
|
|
130
|
+
stream: ExactReadable,
|
|
131
131
|
struct: StructValue
|
|
132
132
|
): BufferLikeFieldValue<this>;
|
|
133
133
|
public override deserialize(
|
|
134
134
|
options: Readonly<StructOptions>,
|
|
135
|
-
stream:
|
|
135
|
+
stream: AsyncExactReadable,
|
|
136
136
|
struct: StructValue
|
|
137
137
|
): Promise<BufferLikeFieldValue<this>>;
|
|
138
138
|
public override deserialize(
|
|
139
139
|
options: Readonly<StructOptions>,
|
|
140
|
-
stream:
|
|
140
|
+
stream: ExactReadable | AsyncExactReadable,
|
|
141
141
|
struct: StructValue
|
|
142
142
|
): ValueOrPromise<BufferLikeFieldValue<this>> {
|
|
143
143
|
return SyncPromise.try(() => {
|
|
@@ -145,7 +145,7 @@ export abstract class BufferLikeFieldDefinition<
|
|
|
145
145
|
if (size === 0) {
|
|
146
146
|
return EMPTY_UINT8_ARRAY;
|
|
147
147
|
} else {
|
|
148
|
-
return stream.
|
|
148
|
+
return stream.readExactly(size);
|
|
149
149
|
}
|
|
150
150
|
})
|
|
151
151
|
.then((array) => {
|
|
@@ -1,16 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
type StructValue,
|
|
1
|
+
import type {
|
|
2
|
+
StructFieldDefinition,
|
|
3
|
+
StructOptions,
|
|
4
|
+
StructValue,
|
|
6
5
|
} from "../../basic/index.js";
|
|
7
|
-
import {
|
|
6
|
+
import { StructFieldValue } from "../../basic/index.js";
|
|
7
|
+
import type { KeysOfType } from "../../utils.js";
|
|
8
8
|
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
BufferLikeFieldValue,
|
|
12
|
-
type BufferFieldSubType,
|
|
13
|
-
} from "./base.js";
|
|
9
|
+
import type { BufferFieldSubType } from "./base.js";
|
|
10
|
+
import { BufferLikeFieldDefinition, BufferLikeFieldValue } from "./base.js";
|
|
14
11
|
|
|
15
12
|
export type LengthField<TFields> = KeysOfType<TFields, number | string>;
|
|
16
13
|
|
package/src/types/number.ts
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
type StructOptions,
|
|
7
|
-
type StructValue,
|
|
1
|
+
import type {
|
|
2
|
+
AsyncExactReadable,
|
|
3
|
+
ExactReadable,
|
|
4
|
+
StructOptions,
|
|
5
|
+
StructValue,
|
|
8
6
|
} from "../basic/index.js";
|
|
7
|
+
import { StructFieldDefinition, StructFieldValue } from "../basic/index.js";
|
|
9
8
|
import { SyncPromise } from "../sync-promise.js";
|
|
10
|
-
import {
|
|
9
|
+
import type { ValueOrPromise } from "../utils.js";
|
|
11
10
|
|
|
12
11
|
export interface NumberFieldType {
|
|
13
12
|
signed: boolean;
|
|
@@ -50,15 +49,12 @@ export namespace NumberFieldType {
|
|
|
50
49
|
signed: false,
|
|
51
50
|
size: 2,
|
|
52
51
|
deserialize(array, littleEndian) {
|
|
53
|
-
// PERF:
|
|
54
|
-
//
|
|
55
|
-
//
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
return
|
|
59
|
-
(((array[1]! << 8) | array[0]!) * (littleEndian as any)) |
|
|
60
|
-
(((array[0]! << 8) | array[1]!) * (!littleEndian as any))
|
|
61
|
-
);
|
|
52
|
+
// PERF: Creating many `DataView`s over small buffers is 90% slower
|
|
53
|
+
// than this. Even if the `DataView` is cached, `DataView#getUint16`
|
|
54
|
+
// is still 1% slower than this.
|
|
55
|
+
const a = (array[1]! << 8) | array[0]!;
|
|
56
|
+
const b = (array[0]! << 8) | array[1]!;
|
|
57
|
+
return littleEndian ? a : b;
|
|
62
58
|
},
|
|
63
59
|
serialize(dataView, offset, value, littleEndian) {
|
|
64
60
|
dataView.setUint16(offset, value, littleEndian);
|
|
@@ -93,18 +89,17 @@ export namespace NumberFieldType {
|
|
|
93
89
|
signed: true,
|
|
94
90
|
size: 4,
|
|
95
91
|
deserialize(array, littleEndian) {
|
|
96
|
-
|
|
97
|
-
(
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
(
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
);
|
|
92
|
+
const a =
|
|
93
|
+
(array[3]! << 24) |
|
|
94
|
+
(array[2]! << 16) |
|
|
95
|
+
(array[1]! << 8) |
|
|
96
|
+
array[0]!;
|
|
97
|
+
const b =
|
|
98
|
+
(array[0]! << 24) |
|
|
99
|
+
(array[1]! << 16) |
|
|
100
|
+
(array[2]! << 8) |
|
|
101
|
+
array[3]!;
|
|
102
|
+
return littleEndian ? a : b;
|
|
108
103
|
},
|
|
109
104
|
serialize(dataView, offset, value, littleEndian) {
|
|
110
105
|
dataView.setInt32(offset, value, littleEndian);
|
|
@@ -138,21 +133,21 @@ export class NumberFieldDefinition<
|
|
|
138
133
|
|
|
139
134
|
public override deserialize(
|
|
140
135
|
options: Readonly<StructOptions>,
|
|
141
|
-
stream:
|
|
136
|
+
stream: ExactReadable,
|
|
142
137
|
struct: StructValue
|
|
143
138
|
): NumberFieldValue<this>;
|
|
144
139
|
public override deserialize(
|
|
145
140
|
options: Readonly<StructOptions>,
|
|
146
|
-
stream:
|
|
141
|
+
stream: AsyncExactReadable,
|
|
147
142
|
struct: StructValue
|
|
148
143
|
): Promise<NumberFieldValue<this>>;
|
|
149
144
|
public override deserialize(
|
|
150
145
|
options: Readonly<StructOptions>,
|
|
151
|
-
stream:
|
|
146
|
+
stream: ExactReadable | AsyncExactReadable,
|
|
152
147
|
struct: StructValue
|
|
153
148
|
): ValueOrPromise<NumberFieldValue<this>> {
|
|
154
149
|
return SyncPromise.try(() => {
|
|
155
|
-
return stream.
|
|
150
|
+
return stream.readExactly(this.getSize());
|
|
156
151
|
})
|
|
157
152
|
.then((array) => {
|
|
158
153
|
const value = this.type.deserialize(
|