@yume-chan/struct 0.0.22 → 0.0.24

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 (51) hide show
  1. package/CHANGELOG.json +18 -0
  2. package/CHANGELOG.md +13 -1
  3. package/LICENSE +1 -1
  4. package/esm/basic/field-value.d.ts +2 -2
  5. package/esm/basic/field-value.d.ts.map +1 -1
  6. package/esm/basic/field-value.js.map +1 -1
  7. package/esm/basic/struct-value.d.ts +6 -2
  8. package/esm/basic/struct-value.d.ts.map +1 -1
  9. package/esm/basic/struct-value.js +5 -0
  10. package/esm/basic/struct-value.js.map +1 -1
  11. package/esm/struct.d.ts +27 -14
  12. package/esm/struct.d.ts.map +1 -1
  13. package/esm/struct.js +31 -18
  14. package/esm/struct.js.map +1 -1
  15. package/esm/sync-promise.d.ts +2 -2
  16. package/esm/sync-promise.d.ts.map +1 -1
  17. package/esm/sync-promise.js.map +1 -1
  18. package/esm/types/bigint.d.ts +13 -14
  19. package/esm/types/bigint.d.ts.map +1 -1
  20. package/esm/types/bigint.js +16 -17
  21. package/esm/types/bigint.js.map +1 -1
  22. package/esm/types/buffer/base.d.ts +31 -27
  23. package/esm/types/buffer/base.d.ts.map +1 -1
  24. package/esm/types/buffer/base.js +25 -26
  25. package/esm/types/buffer/base.js.map +1 -1
  26. package/esm/types/buffer/fixed-length.d.ts +2 -2
  27. package/esm/types/buffer/fixed-length.d.ts.map +1 -1
  28. package/esm/types/buffer/fixed-length.js.map +1 -1
  29. package/esm/types/buffer/variable-length.d.ts +10 -9
  30. package/esm/types/buffer/variable-length.d.ts.map +1 -1
  31. package/esm/types/buffer/variable-length.js +30 -19
  32. package/esm/types/buffer/variable-length.js.map +1 -1
  33. package/esm/types/number.d.ts +13 -13
  34. package/esm/types/number.d.ts.map +1 -1
  35. package/esm/types/number.js +22 -34
  36. package/esm/types/number.js.map +1 -1
  37. package/esm/utils.d.ts.map +1 -1
  38. package/esm/utils.js +6 -4
  39. package/esm/utils.js.map +1 -1
  40. package/package.json +9 -11
  41. package/src/basic/field-value.ts +7 -7
  42. package/src/basic/struct-value.ts +21 -3
  43. package/src/struct.ts +106 -65
  44. package/src/sync-promise.ts +9 -9
  45. package/src/types/bigint.ts +40 -37
  46. package/src/types/buffer/base.ts +48 -47
  47. package/src/types/buffer/fixed-length.ts +9 -4
  48. package/src/types/buffer/variable-length.ts +55 -31
  49. package/src/types/number.ts +32 -39
  50. package/src/utils.ts +6 -4
  51. package/tsconfig.build.tsbuildinfo +1 -1
@@ -1,3 +1,4 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
1
2
  import type {
2
3
  AsyncExactReadable,
3
4
  ExactReadable,
@@ -10,46 +11,49 @@ import type { ValueOrPromise } from "../../utils.js";
10
11
  import { decodeUtf8, encodeUtf8 } from "../../utils.js";
11
12
 
12
13
  /**
13
- * Base class for all types that
14
- * can be converted from an `Uint8Array` when deserialized,
15
- * and need to be converted to an `Uint8Array` when serializing
14
+ * A converter for buffer-like fields.
15
+ * It converts `Uint8Array`s to custom-typed values when deserializing,
16
+ * and convert values back to `Uint8Array`s when serializing.
16
17
  *
17
- * @template TValue The actual TypeScript type of this type
18
- * @template TTypeScriptType Optional another type (should be compatible with `TType`)
19
- * specified by user when creating field definitions.
18
+ * @template TValue The type of the value that the converter converts to/from `Uint8Array`.
19
+ * @template TTypeScriptType Optionally another type to refine `TValue`.
20
+ * For example, `TValue` is `string`, and `TTypeScriptType` is `"foo" | "bar"`.
21
+ * `TValue` is specified by the developer when creating an converter implementation,
22
+ * `TTypeScriptType` is specified by the user when creating a field.
20
23
  */
21
- export abstract class BufferFieldSubType<
24
+ export abstract class BufferFieldConverter<
22
25
  TValue = unknown,
23
26
  TTypeScriptType = TValue,
24
27
  > {
25
28
  readonly TTypeScriptType!: TTypeScriptType;
26
29
 
27
30
  /**
28
- * When implemented in derived classes, converts the type-specific `value` to an `Uint8Array`
31
+ * When implemented in derived classes, converts the custom `value` to an `Uint8Array`
29
32
  *
30
33
  * This function should be "pure", i.e.,
31
34
  * same `value` should always be converted to `Uint8Array`s that have same content.
32
35
  */
33
36
  abstract toBuffer(value: TValue): Uint8Array;
34
37
 
35
- /** When implemented in derived classes, converts the `Uint8Array` to a type-specific value */
38
+ /** When implemented in derived classes, converts the `Uint8Array` to a custom value */
36
39
  abstract toValue(array: Uint8Array): TValue;
37
40
 
38
41
  /**
39
- * When implemented in derived classes, gets the size in byte of the type-specific `value`.
42
+ * When implemented in derived classes, gets the size in byte of the custom `value`.
40
43
  *
41
- * If the size can't be calculated without first converting the `value` back to an `Uint8Array`,
42
- * implementer can returns `-1`, so the caller will get its size by first converting it to
43
- * an `Uint8Array` (and cache the result).
44
+ * If the size can't be determined without first converting the `value` back to an `Uint8Array`,
45
+ * the implementer should return `undefined`. In which case, the caller will call `toBuffer` to
46
+ * convert the value to a `Uint8Array`, then read the length of the `Uint8Array`. The caller can
47
+ * cache the result so the serialization process doesn't need to call `toBuffer` again.
44
48
  */
45
- abstract getSize(value: TValue): number;
49
+ abstract getSize(value: TValue): number | undefined;
46
50
  }
47
51
 
48
- /** An `BufferFieldSubType` that's actually an `Uint8Array` */
49
- export class Uint8ArrayBufferFieldSubType<
52
+ /** An identity converter, doesn't convert to anything else. */
53
+ export class Uint8ArrayBufferFieldConverter<
50
54
  TTypeScriptType = Uint8Array,
51
- > extends BufferFieldSubType<Uint8Array, TTypeScriptType> {
52
- static readonly Instance = new Uint8ArrayBufferFieldSubType();
55
+ > extends BufferFieldConverter<Uint8Array, TTypeScriptType> {
56
+ static readonly Instance = new Uint8ArrayBufferFieldConverter();
53
57
 
54
58
  protected constructor() {
55
59
  super();
@@ -64,15 +68,15 @@ export class Uint8ArrayBufferFieldSubType<
64
68
  }
65
69
 
66
70
  getSize(value: Uint8Array): number {
67
- return value.byteLength;
71
+ return value.length;
68
72
  }
69
73
  }
70
74
 
71
75
  /** An `BufferFieldSubType` that converts between `Uint8Array` and `string` */
72
- export class StringBufferFieldSubType<
76
+ export class StringBufferFieldConverter<
73
77
  TTypeScriptType = string,
74
- > extends BufferFieldSubType<string, TTypeScriptType> {
75
- static readonly Instance = new StringBufferFieldSubType();
78
+ > extends BufferFieldConverter<string, TTypeScriptType> {
79
+ static readonly Instance = new StringBufferFieldConverter();
76
80
 
77
81
  toBuffer(value: string): Uint8Array {
78
82
  return encodeUtf8(value);
@@ -82,30 +86,29 @@ export class StringBufferFieldSubType<
82
86
  return decodeUtf8(array);
83
87
  }
84
88
 
85
- getSize(): number {
86
- // Return `-1`, so `BufferLikeFieldDefinition` will
87
- // convert this `value` into an `Uint8Array` (and cache the result),
88
- // Then get the size from that `Uint8Array`
89
- return -1;
89
+ getSize(): number | undefined {
90
+ // See the note in `BufferFieldConverter.getSize`
91
+ return undefined;
90
92
  }
91
93
  }
92
94
 
93
95
  export const EMPTY_UINT8_ARRAY = new Uint8Array(0);
94
96
 
95
97
  export abstract class BufferLikeFieldDefinition<
96
- TType extends BufferFieldSubType<any, any> = BufferFieldSubType<
98
+ TConverter extends BufferFieldConverter<
97
99
  unknown,
98
100
  unknown
99
- >,
101
+ > = BufferFieldConverter<unknown, unknown>,
100
102
  TOptions = void,
101
103
  TOmitInitKey extends PropertyKey = never,
102
- TTypeScriptType = TType["TTypeScriptType"],
104
+ TTypeScriptType = TConverter["TTypeScriptType"],
103
105
  > extends StructFieldDefinition<TOptions, TTypeScriptType, TOmitInitKey> {
104
- readonly type: TType;
106
+ readonly converter: TConverter;
107
+ readonly TTypeScriptType!: TTypeScriptType;
105
108
 
106
- constructor(type: TType, options: TOptions) {
109
+ constructor(converter: TConverter, options: TOptions) {
107
110
  super(options);
108
- this.type = type;
111
+ this.converter = converter;
109
112
  }
110
113
 
111
114
  protected getDeserializeSize(struct: StructValue): number {
@@ -119,7 +122,7 @@ export abstract class BufferLikeFieldDefinition<
119
122
  create(
120
123
  options: Readonly<StructOptions>,
121
124
  struct: StructValue,
122
- value: TType["TTypeScriptType"],
125
+ value: TTypeScriptType,
123
126
  array?: Uint8Array,
124
127
  ): BufferLikeFieldValue<this> {
125
128
  return new BufferLikeFieldValue(this, options, struct, value, array);
@@ -149,7 +152,7 @@ export abstract class BufferLikeFieldDefinition<
149
152
  }
150
153
  })
151
154
  .then((array) => {
152
- const value = this.type.toValue(array);
155
+ const value = this.converter.toValue(array) as TTypeScriptType;
153
156
  return this.create(options, struct, value, array);
154
157
  })
155
158
  .valueOrPromise();
@@ -158,7 +161,8 @@ export abstract class BufferLikeFieldDefinition<
158
161
 
159
162
  export class BufferLikeFieldValue<
160
163
  TDefinition extends BufferLikeFieldDefinition<
161
- BufferFieldSubType<unknown, unknown>,
164
+ BufferFieldConverter<unknown, unknown>,
165
+ any,
162
166
  any,
163
167
  any
164
168
  >,
@@ -169,7 +173,7 @@ export class BufferLikeFieldValue<
169
173
  definition: TDefinition,
170
174
  options: Readonly<StructOptions>,
171
175
  struct: StructValue,
172
- value: TDefinition["TValue"],
176
+ value: TDefinition["TTypeScriptType"],
173
177
  array?: Uint8Array,
174
178
  ) {
175
179
  super(definition, options, struct, value);
@@ -183,15 +187,12 @@ export class BufferLikeFieldValue<
183
187
  this.array = undefined;
184
188
  }
185
189
 
186
- serialize(dataView: DataView, offset: number): void {
187
- if (!this.array) {
188
- this.array = this.definition.type.toBuffer(this.value);
189
- }
190
-
191
- new Uint8Array(
192
- dataView.buffer,
193
- dataView.byteOffset,
194
- dataView.byteLength,
195
- ).set(this.array, offset);
190
+ override serialize(
191
+ dataView: DataView,
192
+ array: Uint8Array,
193
+ offset: number,
194
+ ): void {
195
+ this.array ??= this.definition.converter.toBuffer(this.value);
196
+ array.set(this.array, offset);
196
197
  }
197
198
  }
@@ -1,4 +1,4 @@
1
- import type { BufferFieldSubType } from "./base.js";
1
+ import type { BufferFieldConverter } from "./base.js";
2
2
  import { BufferLikeFieldDefinition } from "./base.js";
3
3
 
4
4
  export interface FixedLengthBufferLikeFieldOptions {
@@ -6,11 +6,16 @@ export interface FixedLengthBufferLikeFieldOptions {
6
6
  }
7
7
 
8
8
  export class FixedLengthBufferLikeFieldDefinition<
9
- TType extends BufferFieldSubType = BufferFieldSubType,
9
+ TConverter extends BufferFieldConverter = BufferFieldConverter,
10
10
  TOptions extends
11
11
  FixedLengthBufferLikeFieldOptions = FixedLengthBufferLikeFieldOptions,
12
- TTypeScriptType = TType["TTypeScriptType"],
13
- > extends BufferLikeFieldDefinition<TType, TOptions, never, TTypeScriptType> {
12
+ TTypeScriptType = TConverter["TTypeScriptType"],
13
+ > extends BufferLikeFieldDefinition<
14
+ TConverter,
15
+ TOptions,
16
+ never,
17
+ TTypeScriptType
18
+ > {
14
19
  getSize(): number {
15
20
  return this.options.length;
16
21
  }
@@ -1,3 +1,6 @@
1
+ /* eslint-disable @typescript-eslint/no-unsafe-member-access */
2
+ /* eslint-disable @typescript-eslint/no-explicit-any */
3
+
1
4
  import type {
2
5
  StructFieldDefinition,
3
6
  StructOptions,
@@ -6,13 +9,13 @@ import type {
6
9
  import { StructFieldValue } from "../../basic/index.js";
7
10
  import type { KeysOfType } from "../../utils.js";
8
11
 
9
- import type { BufferFieldSubType } from "./base.js";
12
+ import type { BufferFieldConverter } from "./base.js";
10
13
  import { BufferLikeFieldDefinition, BufferLikeFieldValue } from "./base.js";
11
14
 
12
15
  export type LengthField<TFields> = KeysOfType<TFields, number | string>;
13
16
 
14
17
  export interface VariableLengthBufferLikeFieldOptions<
15
- TFields = object,
18
+ TFields extends object = object,
16
19
  TLengthField extends LengthField<TFields> = any,
17
20
  > {
18
21
  /**
@@ -32,12 +35,12 @@ export interface VariableLengthBufferLikeFieldOptions<
32
35
  }
33
36
 
34
37
  export class VariableLengthBufferLikeFieldDefinition<
35
- TType extends BufferFieldSubType = BufferFieldSubType,
38
+ TConverter extends BufferFieldConverter = BufferFieldConverter,
36
39
  TOptions extends
37
40
  VariableLengthBufferLikeFieldOptions = VariableLengthBufferLikeFieldOptions,
38
- TTypeScriptType = TType["TTypeScriptType"],
41
+ TTypeScriptType = TConverter["TTypeScriptType"],
39
42
  > extends BufferLikeFieldDefinition<
40
- TType,
43
+ TConverter,
41
44
  TOptions,
42
45
  TOptions["lengthField"],
43
46
  TTypeScriptType
@@ -88,11 +91,11 @@ export class VariableLengthBufferLikeStructFieldValue<
88
91
  super(definition, options, struct, value, array);
89
92
 
90
93
  if (array) {
91
- this.length = array.byteLength;
94
+ this.length = array.length;
92
95
  }
93
96
 
94
97
  // Patch the associated length field.
95
- const lengthField = this.definition.options.lengthField;
98
+ const lengthField = this.definition.options.lengthField as PropertyKey;
96
99
 
97
100
  const originalValue = struct.get(lengthField);
98
101
  this.lengthFieldValue = new VariableLengthBufferLikeFieldLengthValue(
@@ -102,13 +105,24 @@ export class VariableLengthBufferLikeStructFieldValue<
102
105
  struct.set(lengthField, this.lengthFieldValue);
103
106
  }
104
107
 
105
- override getSize() {
108
+ #tryGetSize() {
109
+ const length = this.definition.converter.getSize(this.value);
110
+ if (length !== undefined && length < 0) {
111
+ throw new Error("Invalid length");
112
+ }
113
+ return length;
114
+ }
115
+
116
+ override getSize(): number {
106
117
  if (this.length === undefined) {
107
- this.length = this.definition.type.getSize(this.value);
108
- if (this.length === -1) {
109
- this.array = this.definition.type.toBuffer(this.value);
110
- this.length = this.array.byteLength;
111
- }
118
+ // first try to get the size from the converter
119
+ this.length = this.#tryGetSize();
120
+ }
121
+
122
+ if (this.length === undefined) {
123
+ // The converter doesn't know the size, so convert the value to a buffer to get its size
124
+ this.array = this.definition.converter.toBuffer(this.value);
125
+ this.length = this.array.length;
112
126
  }
113
127
 
114
128
  return this.length;
@@ -123,39 +137,49 @@ export class VariableLengthBufferLikeStructFieldValue<
123
137
 
124
138
  // Not using `VariableLengthBufferLikeStructFieldValue` directly makes writing tests much easier...
125
139
  type VariableLengthBufferLikeFieldValueLike = StructFieldValue<
126
- StructFieldDefinition<VariableLengthBufferLikeFieldOptions, any, any>
140
+ StructFieldDefinition<
141
+ VariableLengthBufferLikeFieldOptions<any, any>,
142
+ any,
143
+ any
144
+ >
127
145
  >;
128
146
 
129
- export class VariableLengthBufferLikeFieldLengthValue extends StructFieldValue {
130
- protected originalField: StructFieldValue;
147
+ export class VariableLengthBufferLikeFieldLengthValue extends StructFieldValue<
148
+ StructFieldDefinition<unknown, unknown, PropertyKey>
149
+ > {
150
+ protected originalValue: StructFieldValue<
151
+ StructFieldDefinition<unknown, unknown, PropertyKey>
152
+ >;
131
153
 
132
- protected bufferField: VariableLengthBufferLikeFieldValueLike;
154
+ protected bufferValue: VariableLengthBufferLikeFieldValueLike;
133
155
 
134
156
  constructor(
135
- originalField: StructFieldValue,
136
- arrayBufferField: VariableLengthBufferLikeFieldValueLike,
157
+ originalValue: StructFieldValue<
158
+ StructFieldDefinition<unknown, unknown, PropertyKey>
159
+ >,
160
+ bufferValue: VariableLengthBufferLikeFieldValueLike,
137
161
  ) {
138
162
  super(
139
- originalField.definition,
140
- originalField.options,
141
- originalField.struct,
163
+ originalValue.definition,
164
+ originalValue.options,
165
+ originalValue.struct,
142
166
  0,
143
167
  );
144
- this.originalField = originalField;
145
- this.bufferField = arrayBufferField;
168
+ this.originalValue = originalValue;
169
+ this.bufferValue = bufferValue;
146
170
  }
147
171
 
148
172
  override getSize() {
149
- return this.originalField.getSize();
173
+ return this.originalValue.getSize();
150
174
  }
151
175
 
152
176
  override get() {
153
- let value: string | number = this.bufferField.getSize();
177
+ let value: string | number = this.bufferValue.getSize();
154
178
 
155
- const originalValue = this.originalField.get();
179
+ const originalValue = this.originalValue.get();
156
180
  if (typeof originalValue === "string") {
157
181
  value = value.toString(
158
- this.bufferField.definition.options.lengthFieldRadix ?? 10,
182
+ this.bufferValue.definition.options.lengthFieldRadix ?? 10,
159
183
  );
160
184
  }
161
185
 
@@ -167,8 +191,8 @@ export class VariableLengthBufferLikeFieldLengthValue extends StructFieldValue {
167
191
  // It will always be in sync with the buffer size
168
192
  }
169
193
 
170
- serialize(dataView: DataView, offset: number) {
171
- this.originalField.set(this.get());
172
- this.originalField.serialize(dataView, offset);
194
+ serialize(dataView: DataView, array: Uint8Array, offset: number) {
195
+ this.originalValue.set(this.get());
196
+ this.originalValue.serialize(dataView, array, offset);
173
197
  }
174
198
  }
@@ -1,3 +1,11 @@
1
+ import {
2
+ getInt16,
3
+ getInt32,
4
+ getInt8,
5
+ getUint16,
6
+ getUint32,
7
+ } from "@yume-chan/no-data-view";
8
+
1
9
  import type {
2
10
  AsyncExactReadable,
3
11
  ExactReadable,
@@ -8,7 +16,7 @@ import { StructFieldDefinition, StructFieldValue } from "../basic/index.js";
8
16
  import { SyncPromise } from "../sync-promise.js";
9
17
  import type { ValueOrPromise } from "../utils.js";
10
18
 
11
- export interface NumberFieldType {
19
+ export interface NumberFieldVariant {
12
20
  signed: boolean;
13
21
  size: number;
14
22
  deserialize(array: Uint8Array, littleEndian: boolean): number;
@@ -20,8 +28,8 @@ export interface NumberFieldType {
20
28
  ): void;
21
29
  }
22
30
 
23
- export namespace NumberFieldType {
24
- export const Uint8: NumberFieldType = {
31
+ export namespace NumberFieldVariant {
32
+ export const Uint8: NumberFieldVariant = {
25
33
  signed: false,
26
34
  size: 1,
27
35
  deserialize(array) {
@@ -32,73 +40,58 @@ export namespace NumberFieldType {
32
40
  },
33
41
  };
34
42
 
35
- export const Int8: NumberFieldType = {
43
+ export const Int8: NumberFieldVariant = {
36
44
  signed: true,
37
45
  size: 1,
38
46
  deserialize(array) {
39
- const value = Uint8.deserialize(array, false);
40
- return (value << 24) >> 24;
47
+ return getInt8(array, 0);
41
48
  },
42
49
  serialize(dataView, offset, value) {
43
50
  dataView.setInt8(offset, value);
44
51
  },
45
52
  };
46
53
 
47
- export const Uint16: NumberFieldType = {
54
+ export const Uint16: NumberFieldVariant = {
48
55
  signed: false,
49
56
  size: 2,
50
57
  deserialize(array, littleEndian) {
51
58
  // PERF: Creating many `DataView`s over small buffers is 90% slower
52
59
  // than this. Even if the `DataView` is cached, `DataView#getUint16`
53
60
  // is still 1% slower than this.
54
- const a = (array[1]! << 8) | array[0]!;
55
- const b = (array[0]! << 8) | array[1]!;
56
- return littleEndian ? a : b;
61
+ return getUint16(array, 0, littleEndian);
57
62
  },
58
63
  serialize(dataView, offset, value, littleEndian) {
59
64
  dataView.setUint16(offset, value, littleEndian);
60
65
  },
61
66
  };
62
67
 
63
- export const Int16: NumberFieldType = {
68
+ export const Int16: NumberFieldVariant = {
64
69
  signed: true,
65
70
  size: 2,
66
71
  deserialize(array, littleEndian) {
67
- const value = Uint16.deserialize(array, littleEndian);
68
- return (value << 16) >> 16;
72
+ return getInt16(array, 0, littleEndian);
69
73
  },
70
74
  serialize(dataView, offset, value, littleEndian) {
71
75
  dataView.setInt16(offset, value, littleEndian);
72
76
  },
73
77
  };
74
78
 
75
- export const Uint32: NumberFieldType = {
79
+ export const Uint32: NumberFieldVariant = {
76
80
  signed: false,
77
81
  size: 4,
78
82
  deserialize(array, littleEndian) {
79
- const value = Int32.deserialize(array, littleEndian);
80
- return value >>> 0;
83
+ return getUint32(array, 0, littleEndian);
81
84
  },
82
85
  serialize(dataView, offset, value, littleEndian) {
83
86
  dataView.setUint32(offset, value, littleEndian);
84
87
  },
85
88
  };
86
89
 
87
- export const Int32: NumberFieldType = {
90
+ export const Int32: NumberFieldVariant = {
88
91
  signed: true,
89
92
  size: 4,
90
93
  deserialize(array, littleEndian) {
91
- const a =
92
- (array[3]! << 24) |
93
- (array[2]! << 16) |
94
- (array[1]! << 8) |
95
- array[0]!;
96
- const b =
97
- (array[0]! << 24) |
98
- (array[1]! << 16) |
99
- (array[2]! << 8) |
100
- array[3]!;
101
- return littleEndian ? a : b;
94
+ return getInt32(array, 0, littleEndian);
102
95
  },
103
96
  serialize(dataView, offset, value, littleEndian) {
104
97
  dataView.setInt32(offset, value, littleEndian);
@@ -107,19 +100,19 @@ export namespace NumberFieldType {
107
100
  }
108
101
 
109
102
  export class NumberFieldDefinition<
110
- TType extends NumberFieldType = NumberFieldType,
103
+ TVariant extends NumberFieldVariant = NumberFieldVariant,
111
104
  TTypeScriptType = number,
112
105
  > extends StructFieldDefinition<void, TTypeScriptType> {
113
- readonly type: TType;
106
+ readonly variant: TVariant;
114
107
 
115
- constructor(type: TType, typescriptType?: TTypeScriptType) {
108
+ constructor(variant: TVariant, typescriptType?: TTypeScriptType) {
116
109
  void typescriptType;
117
110
  super();
118
- this.type = type;
111
+ this.variant = variant;
119
112
  }
120
113
 
121
114
  getSize(): number {
122
- return this.type.size;
115
+ return this.variant.size;
123
116
  }
124
117
 
125
118
  create(
@@ -149,24 +142,24 @@ export class NumberFieldDefinition<
149
142
  return stream.readExactly(this.getSize());
150
143
  })
151
144
  .then((array) => {
152
- const value = this.type.deserialize(
145
+ const value = this.variant.deserialize(
153
146
  array,
154
147
  options.littleEndian,
155
148
  );
156
- return this.create(options, struct, value as any);
149
+ return this.create(options, struct, value as never);
157
150
  })
158
151
  .valueOrPromise();
159
152
  }
160
153
  }
161
154
 
162
155
  export class NumberFieldValue<
163
- TDefinition extends NumberFieldDefinition<NumberFieldType, any>,
156
+ TDefinition extends NumberFieldDefinition<NumberFieldVariant, unknown>,
164
157
  > extends StructFieldValue<TDefinition> {
165
- serialize(dataView: DataView, offset: number): void {
166
- this.definition.type.serialize(
158
+ serialize(dataView: DataView, array: Uint8Array, offset: number): void {
159
+ this.definition.variant.serialize(
167
160
  dataView,
168
161
  offset,
169
- this.value,
162
+ this.value as never,
170
163
  this.options.littleEndian,
171
164
  );
172
165
  }
package/src/utils.ts CHANGED
@@ -80,13 +80,15 @@ interface GlobalExtension {
80
80
 
81
81
  const { TextEncoder, TextDecoder } = globalThis as unknown as GlobalExtension;
82
82
 
83
- const Utf8Encoder = new TextEncoder();
84
- const Utf8Decoder = new TextDecoder();
83
+ const SharedEncoder = new TextEncoder();
84
+ const SharedDecoder = new TextDecoder();
85
85
 
86
86
  export function encodeUtf8(input: string): Uint8Array {
87
- return Utf8Encoder.encode(input);
87
+ return SharedEncoder.encode(input);
88
88
  }
89
89
 
90
90
  export function decodeUtf8(buffer: ArrayBufferView | ArrayBuffer): string {
91
- return Utf8Decoder.decode(buffer);
91
+ // `TextDecoder` has internal states in stream mode,
92
+ // but this method is not for stream mode, so the instance can be reused
93
+ return SharedDecoder.decode(buffer);
92
94
  }