utilium 1.7.9 → 1.7.11
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/dist/struct.js +33 -40
- package/package.json +1 -1
- package/src/struct.ts +41 -50
package/dist/struct.js
CHANGED
@@ -4,6 +4,25 @@ import { checkInstance, checkStruct, isCustom, isStatic, symbol_metadata } from
|
|
4
4
|
import { _throw } from './misc.js';
|
5
5
|
import { capitalize } from './string.js';
|
6
6
|
export * as Struct from './internal/struct.js';
|
7
|
+
/**
|
8
|
+
* Gets the length of an array in a struct
|
9
|
+
* @param length The numeric length or the name of the field which has the array length (like __counted_by)
|
10
|
+
* @param name The name of the array field— only used for errors
|
11
|
+
*/
|
12
|
+
function _memberLength(struct, length, name) {
|
13
|
+
if (length === undefined)
|
14
|
+
return -1;
|
15
|
+
if (typeof length != 'string')
|
16
|
+
return Number.isSafeInteger(length) && length >= 0
|
17
|
+
? length
|
18
|
+
: _throw(new Error('Array lengths must be natural numbers'));
|
19
|
+
if (!(length in struct))
|
20
|
+
throw new Error(`Can not use non-existent member to count ${name}: ` + length);
|
21
|
+
const n = struct[length];
|
22
|
+
if (typeof n != 'number')
|
23
|
+
throw new Error(`Can not use "${name}" to count ${length}`);
|
24
|
+
return n;
|
25
|
+
}
|
7
26
|
/**
|
8
27
|
* Gets the size in bytes of a type
|
9
28
|
*/
|
@@ -16,8 +35,18 @@ export function sizeof(type) {
|
|
16
35
|
if (isCustom(type))
|
17
36
|
return type[Symbol.size];
|
18
37
|
checkStruct(type);
|
19
|
-
const struct = isStatic(type)
|
20
|
-
|
38
|
+
const { struct } = isStatic(type)
|
39
|
+
? type[symbol_metadata(type)]
|
40
|
+
: type.constructor[symbol_metadata(type.constructor)];
|
41
|
+
if (isStatic(type))
|
42
|
+
return struct.staticSize;
|
43
|
+
let size = struct.staticSize;
|
44
|
+
for (const [name, { type: memberType, length: key }] of struct.members) {
|
45
|
+
if (typeof key != 'string')
|
46
|
+
continue;
|
47
|
+
size += sizeof(memberType) * _memberLength(type, key, name);
|
48
|
+
}
|
49
|
+
return size;
|
21
50
|
}
|
22
51
|
/**
|
23
52
|
* Returns the offset (in bytes) of a member in a struct.
|
@@ -37,36 +66,6 @@ export function offsetof(type, memberName) {
|
|
37
66
|
export function align(value, alignment) {
|
38
67
|
return Math.ceil(value / alignment) * alignment;
|
39
68
|
}
|
40
|
-
/**
|
41
|
-
* Gets the length of an array in a struct
|
42
|
-
* @param length The numeric length or the name of the field which has the array length (like __counted_by)
|
43
|
-
* @param name The name of the array field— only used for errors
|
44
|
-
*/
|
45
|
-
function _memberLength(struct, length, name) {
|
46
|
-
if (length === undefined)
|
47
|
-
return -1;
|
48
|
-
if (typeof length != 'string')
|
49
|
-
return Number.isSafeInteger(length) && length >= 0
|
50
|
-
? length
|
51
|
-
: _throw(new Error('Array lengths must be natural numbers'));
|
52
|
-
if (!(length in struct))
|
53
|
-
throw new Error(`Can not use non-existent member to count ${name}: ` + length);
|
54
|
-
const n = struct[length];
|
55
|
-
if (typeof n != 'number')
|
56
|
-
throw new Error(`Can not use "${name}" to count ${length}`);
|
57
|
-
return n;
|
58
|
-
}
|
59
|
-
/** Compute the size of a struct including dynamically sized members */
|
60
|
-
function _structSize() {
|
61
|
-
const { staticSize, members } = this.constructor[symbol_metadata(this.constructor)].struct;
|
62
|
-
let size = staticSize;
|
63
|
-
for (const [name, { type, length: key }] of members) {
|
64
|
-
if (typeof key != 'string')
|
65
|
-
continue;
|
66
|
-
size += sizeof(type) * _memberLength(this, key, name);
|
67
|
-
}
|
68
|
-
return size;
|
69
|
-
}
|
70
69
|
/**
|
71
70
|
* Decorates a class as a struct
|
72
71
|
*/
|
@@ -90,12 +89,6 @@ export function struct(options = {}) {
|
|
90
89
|
staticSize = align(staticSize, options.align || 1);
|
91
90
|
}
|
92
91
|
context.metadata.struct = { options, members, staticSize };
|
93
|
-
context.addInitializer(function () {
|
94
|
-
Object.defineProperty(this.prototype, Symbol.size, {
|
95
|
-
get: _structSize.bind(this),
|
96
|
-
enumerable: false,
|
97
|
-
});
|
98
|
-
});
|
99
92
|
return target;
|
100
93
|
};
|
101
94
|
}
|
@@ -122,7 +115,7 @@ export function member(type, length) {
|
|
122
115
|
* Serializes a struct into a Uint8Array
|
123
116
|
*/
|
124
117
|
export function serialize(instance) {
|
125
|
-
if (isCustom(instance))
|
118
|
+
if (isCustom(instance) && typeof instance[Symbol.serialize] == 'function')
|
126
119
|
return instance[Symbol.serialize]();
|
127
120
|
checkInstance(instance);
|
128
121
|
const { options, members } = instance.constructor[symbol_metadata(instance.constructor)].struct;
|
@@ -175,7 +168,7 @@ export function serialize(instance) {
|
|
175
168
|
*/
|
176
169
|
export function deserialize(instance, _buffer) {
|
177
170
|
const buffer = toUint8Array(_buffer);
|
178
|
-
if (isCustom(instance))
|
171
|
+
if (isCustom(instance) && typeof instance[Symbol.deserialize] == 'function')
|
179
172
|
return instance[Symbol.deserialize](buffer);
|
180
173
|
checkInstance(instance);
|
181
174
|
const { options, members } = instance.constructor[symbol_metadata(instance.constructor)].struct;
|
package/package.json
CHANGED
package/src/struct.ts
CHANGED
@@ -20,6 +20,31 @@ import { capitalize } from './string.js';
|
|
20
20
|
import type { ClassLike } from './types.js';
|
21
21
|
export * as Struct from './internal/struct.js';
|
22
22
|
|
23
|
+
/**
|
24
|
+
* Gets the length of an array in a struct
|
25
|
+
* @param length The numeric length or the name of the field which has the array length (like __counted_by)
|
26
|
+
* @param name The name of the array field— only used for errors
|
27
|
+
*/
|
28
|
+
function _memberLength<T extends Metadata>(
|
29
|
+
struct: Instance<T>,
|
30
|
+
length: string | number | undefined,
|
31
|
+
name: string
|
32
|
+
): number {
|
33
|
+
if (length === undefined) return -1;
|
34
|
+
if (typeof length != 'string')
|
35
|
+
return Number.isSafeInteger(length) && length >= 0
|
36
|
+
? length
|
37
|
+
: _throw(new Error('Array lengths must be natural numbers'));
|
38
|
+
|
39
|
+
if (!(length in struct)) throw new Error(`Can not use non-existent member to count ${name}: ` + length);
|
40
|
+
|
41
|
+
const n = (struct as any)[length];
|
42
|
+
|
43
|
+
if (typeof n != 'number') throw new Error(`Can not use "${name}" to count ${length}`);
|
44
|
+
|
45
|
+
return n;
|
46
|
+
}
|
47
|
+
|
23
48
|
/**
|
24
49
|
* Gets the size in bytes of a type
|
25
50
|
*/
|
@@ -35,9 +60,20 @@ export function sizeof<T extends TypeLike>(type: T): Size<T> {
|
|
35
60
|
|
36
61
|
checkStruct(type);
|
37
62
|
|
38
|
-
const struct = isStatic(type)
|
63
|
+
const { struct } = isStatic(type)
|
64
|
+
? type[symbol_metadata(type)]
|
65
|
+
: type.constructor[symbol_metadata(type.constructor)];
|
66
|
+
|
67
|
+
if (isStatic(type)) return struct.staticSize as Size<T>;
|
68
|
+
|
69
|
+
let size = struct.staticSize;
|
70
|
+
|
71
|
+
for (const [name, { type: memberType, length: key }] of struct.members) {
|
72
|
+
if (typeof key != 'string') continue;
|
73
|
+
size += sizeof(memberType) * _memberLength(type, key, name);
|
74
|
+
}
|
39
75
|
|
40
|
-
return
|
76
|
+
return size as Size<T>;
|
41
77
|
}
|
42
78
|
|
43
79
|
/**
|
@@ -61,45 +97,6 @@ export function align(value: number, alignment: number): number {
|
|
61
97
|
return Math.ceil(value / alignment) * alignment;
|
62
98
|
}
|
63
99
|
|
64
|
-
/**
|
65
|
-
* Gets the length of an array in a struct
|
66
|
-
* @param length The numeric length or the name of the field which has the array length (like __counted_by)
|
67
|
-
* @param name The name of the array field— only used for errors
|
68
|
-
*/
|
69
|
-
function _memberLength<T extends Metadata>(
|
70
|
-
struct: Instance<T>,
|
71
|
-
length: string | number | undefined,
|
72
|
-
name: string
|
73
|
-
): number {
|
74
|
-
if (length === undefined) return -1;
|
75
|
-
if (typeof length != 'string')
|
76
|
-
return Number.isSafeInteger(length) && length >= 0
|
77
|
-
? length
|
78
|
-
: _throw(new Error('Array lengths must be natural numbers'));
|
79
|
-
|
80
|
-
if (!(length in struct)) throw new Error(`Can not use non-existent member to count ${name}: ` + length);
|
81
|
-
|
82
|
-
const n = (struct as any)[length];
|
83
|
-
|
84
|
-
if (typeof n != 'number') throw new Error(`Can not use "${name}" to count ${length}`);
|
85
|
-
|
86
|
-
return n;
|
87
|
-
}
|
88
|
-
|
89
|
-
/** Compute the size of a struct including dynamically sized members */
|
90
|
-
function _structSize<T extends Metadata>(this: Instance<T>) {
|
91
|
-
const { staticSize, members } = this.constructor[symbol_metadata(this.constructor)].struct;
|
92
|
-
|
93
|
-
let size = staticSize;
|
94
|
-
|
95
|
-
for (const [name, { type, length: key }] of members) {
|
96
|
-
if (typeof key != 'string') continue;
|
97
|
-
size += sizeof(type) * _memberLength(this, key, name);
|
98
|
-
}
|
99
|
-
|
100
|
-
return size;
|
101
|
-
}
|
102
|
-
|
103
100
|
/**
|
104
101
|
* Decorates a class as a struct
|
105
102
|
*/
|
@@ -129,13 +126,6 @@ export function struct(options: Partial<Options> = {}) {
|
|
129
126
|
|
130
127
|
context.metadata.struct = { options, members, staticSize } satisfies Metadata;
|
131
128
|
|
132
|
-
context.addInitializer(function (this: any) {
|
133
|
-
Object.defineProperty(this.prototype, Symbol.size, {
|
134
|
-
get: _structSize.bind(this),
|
135
|
-
enumerable: false,
|
136
|
-
});
|
137
|
-
});
|
138
|
-
|
139
129
|
return target;
|
140
130
|
};
|
141
131
|
}
|
@@ -165,7 +155,7 @@ export function member(type: primitive.Valid | ClassLike, length?: number | stri
|
|
165
155
|
* Serializes a struct into a Uint8Array
|
166
156
|
*/
|
167
157
|
export function serialize(instance: unknown): Uint8Array {
|
168
|
-
if (isCustom(instance)) return instance[Symbol.serialize]!();
|
158
|
+
if (isCustom(instance) && typeof instance[Symbol.serialize] == 'function') return instance[Symbol.serialize]!();
|
169
159
|
|
170
160
|
checkInstance(instance);
|
171
161
|
const { options, members } = instance.constructor[symbol_metadata(instance.constructor)].struct;
|
@@ -232,7 +222,8 @@ export function serialize(instance: unknown): Uint8Array {
|
|
232
222
|
export function deserialize(instance: unknown, _buffer: ArrayBufferLike | ArrayBufferView) {
|
233
223
|
const buffer = toUint8Array(_buffer);
|
234
224
|
|
235
|
-
if (isCustom(instance)
|
225
|
+
if (isCustom(instance) && typeof instance[Symbol.deserialize] == 'function')
|
226
|
+
return instance[Symbol.deserialize]!(buffer);
|
236
227
|
|
237
228
|
checkInstance(instance);
|
238
229
|
const { options, members } = instance.constructor[symbol_metadata(instance.constructor)].struct;
|