utilium 1.7.11 → 1.7.12
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/debugging.d.ts +12 -0
- package/dist/debugging.js +17 -0
- package/dist/internal/struct.d.ts +17 -11
- package/dist/internal/struct.js +18 -21
- package/dist/struct.d.ts +1 -1
- package/dist/struct.js +116 -82
- package/package.json +1 -1
- package/src/debugging.ts +19 -0
- package/src/internal/struct.ts +38 -36
- package/src/struct.ts +149 -90
package/dist/debugging.d.ts
CHANGED
@@ -27,4 +27,16 @@ type LoggableDecoratorContext = Exclude<DecoratorContext, ClassFieldDecoratorCon
|
|
27
27
|
* Create a function that can be used to decorate classes and non-field members.
|
28
28
|
*/
|
29
29
|
export declare function createLogDecorator(options: CreateLoggerOptions): <T extends (...args: any[]) => any>(value: T, context: LoggableDecoratorContext) => T;
|
30
|
+
/**
|
31
|
+
* @internal @hidden
|
32
|
+
*/
|
33
|
+
export declare let U_DEBUG: boolean;
|
34
|
+
/**
|
35
|
+
* @internal @hidden
|
36
|
+
*/
|
37
|
+
export declare function _setDebug(value: boolean): void;
|
38
|
+
/**
|
39
|
+
* @internal @hidden
|
40
|
+
*/
|
41
|
+
export declare function _debugLog(...text: any[]): void;
|
30
42
|
export {};
|
package/dist/debugging.js
CHANGED
@@ -53,3 +53,20 @@ export function createLogDecorator(options) {
|
|
53
53
|
};
|
54
54
|
};
|
55
55
|
}
|
56
|
+
/**
|
57
|
+
* @internal @hidden
|
58
|
+
*/
|
59
|
+
export let U_DEBUG = 'process' in globalThis && 'env' in globalThis.process && globalThis.process.env.U_DEBUG == 'true';
|
60
|
+
/**
|
61
|
+
* @internal @hidden
|
62
|
+
*/
|
63
|
+
export function _setDebug(value) {
|
64
|
+
U_DEBUG = value;
|
65
|
+
}
|
66
|
+
/**
|
67
|
+
* @internal @hidden
|
68
|
+
*/
|
69
|
+
export function _debugLog(...text) {
|
70
|
+
if (U_DEBUG)
|
71
|
+
console.debug('[U]', ...text);
|
72
|
+
}
|
@@ -10,7 +10,7 @@ declare global {
|
|
10
10
|
readonly deserialize: unique symbol;
|
11
11
|
}
|
12
12
|
}
|
13
|
-
export type TypeLike = Custom | Like | primitive.Valid;
|
13
|
+
export type TypeLike = Custom | Like | primitive.Valid | undefined | null;
|
14
14
|
export type Type = Custom | Static | primitive.Typename;
|
15
15
|
/**
|
16
16
|
* Member initialization data
|
@@ -30,22 +30,31 @@ export interface Options {
|
|
30
30
|
isUnion: boolean;
|
31
31
|
}
|
32
32
|
export interface Member {
|
33
|
+
name: string;
|
33
34
|
type: Type;
|
34
|
-
|
35
|
+
staticOffset: number;
|
35
36
|
length?: number | string;
|
37
|
+
/** A C-style type/name declaration string, used for diagnostics */
|
38
|
+
decl: string;
|
36
39
|
}
|
37
40
|
export interface Metadata {
|
38
41
|
options: Partial<Options>;
|
39
42
|
members: Map<string, Member>;
|
40
|
-
init?: MemberInit[];
|
41
43
|
staticSize: number;
|
44
|
+
isDynamic: boolean;
|
42
45
|
}
|
43
46
|
type _DecoratorMetadata<T extends Metadata = Metadata> = DecoratorMetadata & {
|
44
|
-
struct?:
|
47
|
+
struct?: T;
|
48
|
+
structInit?: MemberInit[];
|
45
49
|
};
|
46
50
|
export interface DecoratorContext<T extends Metadata = Metadata> {
|
47
51
|
metadata: _DecoratorMetadata<T>;
|
48
52
|
}
|
53
|
+
/**
|
54
|
+
* Initializes the struct metadata for a class
|
55
|
+
* This also handles copying metadata from parent classes
|
56
|
+
*/
|
57
|
+
export declare function initMetadata(context: DecoratorContext): MemberInit[];
|
49
58
|
export type MemberContext = ClassMemberDecoratorContext & DecoratorContext;
|
50
59
|
export interface Static<T extends Metadata = Metadata> {
|
51
60
|
[Symbol.metadata]: {
|
@@ -63,12 +72,9 @@ export declare function isValidMetadata<T extends Metadata = Metadata>(arg: unkn
|
|
63
72
|
/**
|
64
73
|
* Polyfill context.metadata
|
65
74
|
* @see https://github.com/microsoft/TypeScript/issues/53461
|
75
|
+
* @internal @hidden
|
66
76
|
*/
|
67
|
-
export declare function
|
68
|
-
/**
|
69
|
-
* Gets a reference to Symbol.metadata, even on platforms that do not expose it globally (like Node)
|
70
|
-
*/
|
71
|
-
export declare function symbol_metadata(arg: ClassLike): typeof Symbol.metadata;
|
77
|
+
export declare function _polyfill_metadata(target: object): void;
|
72
78
|
export declare function isStatic<T extends Metadata = Metadata>(arg: unknown): arg is Static<T>;
|
73
79
|
export interface Instance<T extends Metadata = Metadata> {
|
74
80
|
constructor: Static<T>;
|
@@ -90,7 +96,7 @@ export interface Custom {
|
|
90
96
|
}
|
91
97
|
export declare function isCustom(arg: unknown): arg is Custom;
|
92
98
|
export type Like<T extends Metadata = Metadata> = InstanceLike<T> | StaticLike<T>;
|
93
|
-
export type Size<T extends TypeLike> = T extends {
|
94
|
-
readonly [Symbol.size]: infer S;
|
99
|
+
export type Size<T extends TypeLike> = T extends undefined | null ? 0 : T extends {
|
100
|
+
readonly [Symbol.size]: infer S extends number;
|
95
101
|
} ? S : T extends primitive.Valid ? primitive.Size<T> : number;
|
96
102
|
export {};
|
package/dist/internal/struct.js
CHANGED
@@ -1,22 +1,32 @@
|
|
1
|
+
/**
|
2
|
+
* Polyfill Symbol.metadata
|
3
|
+
* @see https://github.com/microsoft/TypeScript/issues/53461
|
4
|
+
*/
|
5
|
+
Symbol.metadata ??= Symbol.for('Symbol.metadata');
|
1
6
|
Object.assign(Symbol, {
|
2
7
|
size: Symbol('uSize'),
|
3
8
|
serialize: Symbol('uSerialize'),
|
4
9
|
deserialize: Symbol('uDeserialize'),
|
5
10
|
});
|
11
|
+
/**
|
12
|
+
* Initializes the struct metadata for a class
|
13
|
+
* This also handles copying metadata from parent classes
|
14
|
+
*/
|
15
|
+
export function initMetadata(context) {
|
16
|
+
context.metadata ??= {};
|
17
|
+
context.metadata.structInit = [...(context.metadata.structInit ?? [])];
|
18
|
+
return context.metadata.structInit;
|
19
|
+
}
|
6
20
|
export function isValidMetadata(arg) {
|
7
21
|
return arg != null && typeof arg == 'object' && 'struct' in arg;
|
8
22
|
}
|
9
|
-
/**
|
10
|
-
* Polyfill Symbol.metadata
|
11
|
-
* @see https://github.com/microsoft/TypeScript/issues/53461
|
12
|
-
*/
|
13
|
-
Symbol.metadata ??= Symbol.for('Symbol.metadata');
|
14
23
|
/**
|
15
24
|
* Polyfill context.metadata
|
16
25
|
* @see https://github.com/microsoft/TypeScript/issues/53461
|
26
|
+
* @internal @hidden
|
17
27
|
*/
|
18
|
-
export function
|
19
|
-
if (
|
28
|
+
export function _polyfill_metadata(target) {
|
29
|
+
if (Symbol.metadata in target)
|
20
30
|
return;
|
21
31
|
Object.defineProperty(target, Symbol.metadata, {
|
22
32
|
enumerable: true,
|
@@ -25,21 +35,8 @@ export function _polyfill_contextMetadata(target) {
|
|
25
35
|
value: Object.create(null),
|
26
36
|
});
|
27
37
|
}
|
28
|
-
/**
|
29
|
-
* Gets a reference to Symbol.metadata, even on platforms that do not expose it globally (like Node)
|
30
|
-
*/
|
31
|
-
export function symbol_metadata(arg) {
|
32
|
-
const symbol_metadata = Symbol.metadata || Object.getOwnPropertySymbols(arg).find(s => s.description == 'Symbol.metadata');
|
33
|
-
_polyfill_contextMetadata(arg);
|
34
|
-
if (!symbol_metadata) {
|
35
|
-
throw new ReferenceError('Could not get a reference to Symbol.metadata');
|
36
|
-
}
|
37
|
-
return symbol_metadata;
|
38
|
-
}
|
39
38
|
export function isStatic(arg) {
|
40
|
-
return
|
41
|
-
&& symbol_metadata(arg) in arg
|
42
|
-
&& isValidMetadata(arg[symbol_metadata(arg)]));
|
39
|
+
return typeof arg == 'function' && Symbol.metadata in arg && isValidMetadata(arg[Symbol.metadata]);
|
43
40
|
}
|
44
41
|
export function isInstance(arg) {
|
45
42
|
return arg != null && typeof arg == 'object' && isStatic(arg.constructor);
|
package/dist/struct.d.ts
CHANGED
@@ -5,7 +5,7 @@ export * as Struct from './internal/struct.js';
|
|
5
5
|
/**
|
6
6
|
* Gets the size in bytes of a type
|
7
7
|
*/
|
8
|
-
export declare function sizeof<T extends TypeLike>(type: T): Size<T>;
|
8
|
+
export declare function sizeof<T extends TypeLike>(type: T | T[]): Size<T>;
|
9
9
|
/**
|
10
10
|
* Returns the offset (in bytes) of a member in a struct.
|
11
11
|
*/
|
package/dist/struct.js
CHANGED
@@ -1,32 +1,23 @@
|
|
1
1
|
import { toUint8Array } from './buffer.js';
|
2
|
+
import { _debugLog } from './debugging.js';
|
2
3
|
import * as primitive from './internal/primitives.js';
|
3
|
-
import { checkInstance, checkStruct, isCustom, isStatic,
|
4
|
+
import { _polyfill_metadata, checkInstance, checkStruct, initMetadata, isCustom, isInstance, isStatic, } from './internal/struct.js';
|
4
5
|
import { _throw } from './misc.js';
|
5
6
|
import { capitalize } from './string.js';
|
6
7
|
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
|
-
}
|
26
8
|
/**
|
27
9
|
* Gets the size in bytes of a type
|
28
10
|
*/
|
29
11
|
export function sizeof(type) {
|
12
|
+
if (type === undefined || type === null)
|
13
|
+
return 0;
|
14
|
+
if (Array.isArray(type)) {
|
15
|
+
let size = 0;
|
16
|
+
for (let i = 0; i < type.length; i++) {
|
17
|
+
size += sizeof(type[i]);
|
18
|
+
}
|
19
|
+
return size;
|
20
|
+
}
|
30
21
|
// primitive
|
31
22
|
if (typeof type == 'string') {
|
32
23
|
primitive.checkValid(type);
|
@@ -35,16 +26,18 @@ export function sizeof(type) {
|
|
35
26
|
if (isCustom(type))
|
36
27
|
return type[Symbol.size];
|
37
28
|
checkStruct(type);
|
38
|
-
const
|
39
|
-
|
40
|
-
|
29
|
+
const constructor = isStatic(type) ? type : type.constructor;
|
30
|
+
_polyfill_metadata(constructor);
|
31
|
+
const { struct } = constructor[Symbol.metadata];
|
41
32
|
if (isStatic(type))
|
42
33
|
return struct.staticSize;
|
43
34
|
let size = struct.staticSize;
|
44
|
-
for (const
|
45
|
-
if (typeof
|
35
|
+
for (const member of struct.members.values()) {
|
36
|
+
if (typeof member.length != 'string')
|
46
37
|
continue;
|
47
|
-
|
38
|
+
for (let i = 0; i < type[member.length]; i++) {
|
39
|
+
size += sizeof(type[member.name][i]);
|
40
|
+
}
|
48
41
|
}
|
49
42
|
return size;
|
50
43
|
}
|
@@ -53,12 +46,20 @@ export function sizeof(type) {
|
|
53
46
|
*/
|
54
47
|
export function offsetof(type, memberName) {
|
55
48
|
checkStruct(type);
|
56
|
-
const
|
57
|
-
|
58
|
-
const
|
59
|
-
if (!
|
60
|
-
|
61
|
-
|
49
|
+
const constructor = isStatic(type) ? type : type.constructor;
|
50
|
+
_polyfill_metadata(constructor);
|
51
|
+
const { struct } = constructor[Symbol.metadata];
|
52
|
+
if (isStatic(type) || !struct.isDynamic) {
|
53
|
+
return (struct.members.get(memberName)?.staticOffset
|
54
|
+
?? _throw(new Error('Struct does not have member: ' + memberName)));
|
55
|
+
}
|
56
|
+
let offset = 0;
|
57
|
+
for (const member of struct.members.values()) {
|
58
|
+
if (member.name == memberName)
|
59
|
+
return offset;
|
60
|
+
offset += sizeof(type[member.name]);
|
61
|
+
}
|
62
|
+
throw new Error('Struct does not have member: ' + memberName);
|
62
63
|
}
|
63
64
|
/**
|
64
65
|
* Aligns a number
|
@@ -71,24 +72,35 @@ export function align(value, alignment) {
|
|
71
72
|
*/
|
72
73
|
export function struct(options = {}) {
|
73
74
|
return function _decorateStruct(target, context) {
|
74
|
-
context.metadata ??= {};
|
75
|
-
context.metadata.struct ??= {};
|
76
|
-
context.metadata.struct.init ??= [];
|
77
|
-
let staticSize = 0;
|
78
75
|
const members = new Map();
|
79
|
-
|
76
|
+
let staticSize = 0, isDynamic = false;
|
77
|
+
for (const { name, type, length } of initMetadata(context)) {
|
80
78
|
if (!primitive.isValid(type) && !isStatic(type))
|
81
79
|
throw new TypeError('Not a valid type: ' + type);
|
80
|
+
if (typeof length == 'string') {
|
81
|
+
const countedBy = members.get(length);
|
82
|
+
if (!countedBy)
|
83
|
+
throw new Error(`"${length}" is undefined or declared after "${name}"`);
|
84
|
+
if (!primitive.isType(countedBy.type))
|
85
|
+
throw new Error(`"${length}" is not a number and cannot be used to count "${name}"`);
|
86
|
+
}
|
87
|
+
let decl = `${typeof type == 'string' ? type : type.name} ${name}`;
|
88
|
+
if (length !== undefined)
|
89
|
+
decl += `[${length}]`;
|
82
90
|
members.set(name, {
|
83
|
-
|
91
|
+
name,
|
92
|
+
staticOffset: options.isUnion ? 0 : staticSize,
|
84
93
|
type: primitive.isValid(type) ? primitive.normalize(type) : type,
|
85
94
|
length,
|
95
|
+
decl,
|
86
96
|
});
|
87
97
|
const memberSize = typeof length == 'string' ? 0 : sizeof(type) * (length || 1);
|
98
|
+
isDynamic ||= typeof length == 'string';
|
88
99
|
staticSize = options.isUnion ? Math.max(staticSize, memberSize) : staticSize + memberSize;
|
89
100
|
staticSize = align(staticSize, options.align || 1);
|
101
|
+
_debugLog('define', target.name + '.' + name);
|
90
102
|
}
|
91
|
-
context.metadata.struct = { options, members, staticSize };
|
103
|
+
context.metadata.struct = { options, members, staticSize, isDynamic };
|
92
104
|
return target;
|
93
105
|
};
|
94
106
|
}
|
@@ -104,13 +116,20 @@ export function member(type, length) {
|
|
104
116
|
}
|
105
117
|
if (!name)
|
106
118
|
throw new ReferenceError('Invalid name for struct member');
|
107
|
-
context.
|
108
|
-
context.metadata.struct ??= {};
|
109
|
-
context.metadata.struct.init ??= [];
|
110
|
-
context.metadata.struct.init.push({ name, type, length });
|
119
|
+
initMetadata(context).push({ name, type, length });
|
111
120
|
return value;
|
112
121
|
};
|
113
122
|
}
|
123
|
+
/** Gets the length of a member */
|
124
|
+
function _memberLength(instance, member) {
|
125
|
+
if (member.length === undefined)
|
126
|
+
return -1;
|
127
|
+
if (typeof member.length == 'string')
|
128
|
+
return instance[member.length];
|
129
|
+
return Number.isSafeInteger(member.length) && member.length >= 0
|
130
|
+
? member.length
|
131
|
+
: _throw(new Error('Array lengths must be natural numbers'));
|
132
|
+
}
|
114
133
|
/**
|
115
134
|
* Serializes a struct into a Uint8Array
|
116
135
|
*/
|
@@ -118,47 +137,53 @@ export function serialize(instance) {
|
|
118
137
|
if (isCustom(instance) && typeof instance[Symbol.serialize] == 'function')
|
119
138
|
return instance[Symbol.serialize]();
|
120
139
|
checkInstance(instance);
|
121
|
-
|
122
|
-
const
|
140
|
+
_polyfill_metadata(instance.constructor);
|
141
|
+
const { options, members } = instance.constructor[Symbol.metadata].struct;
|
142
|
+
const size = sizeof(instance);
|
143
|
+
const buffer = new Uint8Array(size);
|
123
144
|
const view = new DataView(buffer.buffer);
|
145
|
+
_debugLog('serialize', instance.constructor.name);
|
146
|
+
let offset = 0, nextOffset = 0;
|
124
147
|
// for unions we should write members in ascending last modified order, but we don't have that info.
|
125
|
-
for (const
|
126
|
-
const length = _memberLength(instance,
|
148
|
+
for (const member of members.values()) {
|
149
|
+
const length = _memberLength(instance, member);
|
150
|
+
_debugLog('\t', member.decl);
|
127
151
|
for (let i = 0; i < Math.abs(length); i++) {
|
128
|
-
|
129
|
-
let value = length != -1 ? instance[name][i] : instance[name];
|
152
|
+
let value = length != -1 ? instance[member.name][i] : instance[member.name];
|
130
153
|
if (typeof value == 'string') {
|
131
154
|
value = value.charCodeAt(0);
|
132
155
|
}
|
133
|
-
|
134
|
-
|
156
|
+
offset = nextOffset;
|
157
|
+
nextOffset += isInstance(value) ? sizeof(value) : sizeof(member.type);
|
158
|
+
if (!primitive.isType(member.type)) {
|
159
|
+
buffer.set(value ? serialize(value) : new Uint8Array(sizeof(member.type)), offset);
|
135
160
|
continue;
|
136
161
|
}
|
137
|
-
const fn = `set${capitalize(type)}`;
|
162
|
+
const fn = `set${capitalize(member.type)}`;
|
138
163
|
if (fn == 'setInt64') {
|
139
|
-
view.setBigInt64(
|
164
|
+
view.setBigInt64(offset, BigInt(value), !options.bigEndian);
|
140
165
|
continue;
|
141
166
|
}
|
142
167
|
if (fn == 'setUint64') {
|
143
|
-
view.setBigUint64(
|
168
|
+
view.setBigUint64(offset, BigInt(value), !options.bigEndian);
|
144
169
|
continue;
|
145
170
|
}
|
146
171
|
if (fn == 'setInt128') {
|
147
|
-
view.setBigUint64(
|
148
|
-
view.setBigInt64(
|
172
|
+
view.setBigUint64(offset + (!options.bigEndian ? 0 : 8), value & primitive.mask64, !options.bigEndian);
|
173
|
+
view.setBigInt64(offset + (!options.bigEndian ? 8 : 0), value >> BigInt(64), !options.bigEndian);
|
149
174
|
continue;
|
150
175
|
}
|
151
176
|
if (fn == 'setUint128') {
|
152
|
-
view.setBigUint64(
|
153
|
-
view.setBigUint64(
|
177
|
+
view.setBigUint64(offset + (!options.bigEndian ? 0 : 8), value & primitive.mask64, !options.bigEndian);
|
178
|
+
view.setBigUint64(offset + (!options.bigEndian ? 8 : 0), value >> BigInt(64), !options.bigEndian);
|
154
179
|
continue;
|
155
180
|
}
|
156
181
|
if (fn == 'setFloat128') {
|
157
|
-
view.setFloat64(
|
158
|
-
view.setBigUint64(
|
182
|
+
view.setFloat64(offset + (!options.bigEndian ? 0 : 8), Number(value), !options.bigEndian);
|
183
|
+
view.setBigUint64(offset + (!options.bigEndian ? 8 : 0), BigInt(0), !options.bigEndian);
|
159
184
|
continue;
|
160
185
|
}
|
161
|
-
view[fn](
|
186
|
+
view[fn](offset, Number(value), !options.bigEndian);
|
162
187
|
}
|
163
188
|
}
|
164
189
|
return buffer;
|
@@ -171,53 +196,62 @@ export function deserialize(instance, _buffer) {
|
|
171
196
|
if (isCustom(instance) && typeof instance[Symbol.deserialize] == 'function')
|
172
197
|
return instance[Symbol.deserialize](buffer);
|
173
198
|
checkInstance(instance);
|
174
|
-
|
199
|
+
_polyfill_metadata(instance.constructor);
|
200
|
+
const { options, members } = instance.constructor[Symbol.metadata].struct;
|
175
201
|
const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
176
|
-
|
177
|
-
|
202
|
+
_debugLog('deserialize', instance.constructor.name);
|
203
|
+
let offset = 0, nextOffset = 0;
|
204
|
+
for (const member of members.values()) {
|
205
|
+
const length = _memberLength(instance, member);
|
206
|
+
_debugLog('\t', member.decl);
|
178
207
|
for (let i = 0; i < Math.abs(length); i++) {
|
179
|
-
let object = length != -1 ? instance[name] : instance;
|
180
|
-
const key = length != -1 ? i : name
|
181
|
-
|
182
|
-
|
183
|
-
|
208
|
+
let object = length != -1 ? instance[member.name] : instance;
|
209
|
+
const key = length != -1 ? i : member.name;
|
210
|
+
offset = nextOffset;
|
211
|
+
if (!isInstance(object[key]))
|
212
|
+
nextOffset += sizeof(member.type);
|
213
|
+
if (typeof instance[member.name] == 'string') {
|
214
|
+
instance[member.name] =
|
215
|
+
instance[member.name].slice(0, i)
|
216
|
+
+ String.fromCharCode(view.getUint8(offset))
|
217
|
+
+ instance[member.name].slice(i + 1);
|
184
218
|
continue;
|
185
219
|
}
|
186
|
-
if (!primitive.isType(type)) {
|
187
|
-
if (object[key] === null || object[key] === undefined)
|
220
|
+
if (!primitive.isType(member.type)) {
|
221
|
+
if (object[key] === null || object[key] === undefined)
|
188
222
|
continue;
|
189
|
-
|
190
|
-
|
223
|
+
deserialize(object[key], new Uint8Array(buffer.subarray(offset)));
|
224
|
+
nextOffset += sizeof(object[key]);
|
191
225
|
continue;
|
192
226
|
}
|
193
227
|
if (length && length != -1)
|
194
228
|
object ||= [];
|
195
|
-
const fn = `get${capitalize(type)}`;
|
229
|
+
const fn = `get${capitalize(member.type)}`;
|
196
230
|
if (fn == 'getInt64') {
|
197
|
-
object[key] = view.getBigInt64(
|
231
|
+
object[key] = view.getBigInt64(offset, !options.bigEndian);
|
198
232
|
continue;
|
199
233
|
}
|
200
234
|
if (fn == 'getUint64') {
|
201
|
-
object[key] = view.getBigUint64(
|
235
|
+
object[key] = view.getBigUint64(offset, !options.bigEndian);
|
202
236
|
continue;
|
203
237
|
}
|
204
238
|
if (fn == 'getInt128') {
|
205
239
|
object[key] =
|
206
|
-
(view.getBigInt64(
|
207
|
-
| view.getBigUint64(
|
240
|
+
(view.getBigInt64(offset + (!options.bigEndian ? 8 : 0), !options.bigEndian) << BigInt(64))
|
241
|
+
| view.getBigUint64(offset + (!options.bigEndian ? 0 : 8), !options.bigEndian);
|
208
242
|
continue;
|
209
243
|
}
|
210
244
|
if (fn == 'getUint128') {
|
211
245
|
object[key] =
|
212
|
-
(view.getBigUint64(
|
213
|
-
| view.getBigUint64(
|
246
|
+
(view.getBigUint64(offset + (!options.bigEndian ? 8 : 0), !options.bigEndian) << BigInt(64))
|
247
|
+
| view.getBigUint64(offset + (!options.bigEndian ? 0 : 8), !options.bigEndian);
|
214
248
|
continue;
|
215
249
|
}
|
216
250
|
if (fn == 'getFloat128') {
|
217
|
-
object[key] = view.getFloat64(
|
251
|
+
object[key] = view.getFloat64(offset + (!options.bigEndian ? 0 : 8), !options.bigEndian);
|
218
252
|
continue;
|
219
253
|
}
|
220
|
-
object[key] = view[fn](
|
254
|
+
object[key] = view[fn](offset, !options.bigEndian);
|
221
255
|
}
|
222
256
|
}
|
223
257
|
}
|
package/package.json
CHANGED
package/src/debugging.ts
CHANGED
@@ -92,3 +92,22 @@ export function createLogDecorator(options: CreateLoggerOptions) {
|
|
92
92
|
} as T;
|
93
93
|
};
|
94
94
|
}
|
95
|
+
|
96
|
+
/**
|
97
|
+
* @internal @hidden
|
98
|
+
*/
|
99
|
+
export let U_DEBUG = 'process' in globalThis && 'env' in globalThis.process && globalThis.process.env.U_DEBUG == 'true';
|
100
|
+
|
101
|
+
/**
|
102
|
+
* @internal @hidden
|
103
|
+
*/
|
104
|
+
export function _setDebug(value: boolean) {
|
105
|
+
U_DEBUG = value;
|
106
|
+
}
|
107
|
+
|
108
|
+
/**
|
109
|
+
* @internal @hidden
|
110
|
+
*/
|
111
|
+
export function _debugLog(...text: any[]) {
|
112
|
+
if (U_DEBUG) console.debug('[U]', ...text);
|
113
|
+
}
|
package/src/internal/struct.ts
CHANGED
@@ -14,13 +14,19 @@ declare global {
|
|
14
14
|
}
|
15
15
|
}
|
16
16
|
|
17
|
+
/**
|
18
|
+
* Polyfill Symbol.metadata
|
19
|
+
* @see https://github.com/microsoft/TypeScript/issues/53461
|
20
|
+
*/
|
21
|
+
(Symbol as { metadata: symbol }).metadata ??= Symbol.for('Symbol.metadata');
|
22
|
+
|
17
23
|
Object.assign(Symbol, {
|
18
24
|
size: Symbol('uSize'),
|
19
25
|
serialize: Symbol('uSerialize'),
|
20
26
|
deserialize: Symbol('uDeserialize'),
|
21
27
|
});
|
22
28
|
|
23
|
-
export type TypeLike = Custom | Like | primitive.Valid;
|
29
|
+
export type TypeLike = Custom | Like | primitive.Valid | undefined | null;
|
24
30
|
|
25
31
|
export type Type = Custom | Static | primitive.Typename;
|
26
32
|
|
@@ -44,26 +50,43 @@ export interface Options {
|
|
44
50
|
}
|
45
51
|
|
46
52
|
export interface Member {
|
53
|
+
name: string;
|
47
54
|
type: Type;
|
48
|
-
|
55
|
+
staticOffset: number;
|
49
56
|
length?: number | string;
|
57
|
+
|
58
|
+
/** A C-style type/name declaration string, used for diagnostics */
|
59
|
+
decl: string;
|
50
60
|
}
|
51
61
|
|
52
62
|
export interface Metadata {
|
53
63
|
options: Partial<Options>;
|
54
64
|
members: Map<string, Member>;
|
55
|
-
init?: MemberInit[];
|
56
65
|
staticSize: number;
|
66
|
+
isDynamic: boolean;
|
57
67
|
}
|
58
68
|
|
59
69
|
type _DecoratorMetadata<T extends Metadata = Metadata> = DecoratorMetadata & {
|
60
|
-
struct?:
|
70
|
+
struct?: T;
|
71
|
+
structInit?: MemberInit[];
|
61
72
|
};
|
62
73
|
|
63
74
|
export interface DecoratorContext<T extends Metadata = Metadata> {
|
64
75
|
metadata: _DecoratorMetadata<T>;
|
65
76
|
}
|
66
77
|
|
78
|
+
/**
|
79
|
+
* Initializes the struct metadata for a class
|
80
|
+
* This also handles copying metadata from parent classes
|
81
|
+
*/
|
82
|
+
export function initMetadata(context: DecoratorContext): MemberInit[] {
|
83
|
+
context.metadata ??= {};
|
84
|
+
|
85
|
+
context.metadata.structInit = [...(context.metadata.structInit ?? [])];
|
86
|
+
|
87
|
+
return context.metadata.structInit;
|
88
|
+
}
|
89
|
+
|
67
90
|
export type MemberContext = ClassMemberDecoratorContext & DecoratorContext;
|
68
91
|
|
69
92
|
export interface Static<T extends Metadata = Metadata> {
|
@@ -84,18 +107,13 @@ export function isValidMetadata<T extends Metadata = Metadata>(
|
|
84
107
|
return arg != null && typeof arg == 'object' && 'struct' in arg;
|
85
108
|
}
|
86
109
|
|
87
|
-
/**
|
88
|
-
* Polyfill Symbol.metadata
|
89
|
-
* @see https://github.com/microsoft/TypeScript/issues/53461
|
90
|
-
*/
|
91
|
-
(Symbol as { metadata: symbol }).metadata ??= Symbol.for('Symbol.metadata');
|
92
|
-
|
93
110
|
/**
|
94
111
|
* Polyfill context.metadata
|
95
112
|
* @see https://github.com/microsoft/TypeScript/issues/53461
|
113
|
+
* @internal @hidden
|
96
114
|
*/
|
97
|
-
export function
|
98
|
-
if (
|
115
|
+
export function _polyfill_metadata(target: object): void {
|
116
|
+
if (Symbol.metadata in target) return;
|
99
117
|
|
100
118
|
Object.defineProperty(target, Symbol.metadata, {
|
101
119
|
enumerable: true,
|
@@ -105,26 +123,8 @@ export function _polyfill_contextMetadata(target: object): void {
|
|
105
123
|
});
|
106
124
|
}
|
107
125
|
|
108
|
-
/**
|
109
|
-
* Gets a reference to Symbol.metadata, even on platforms that do not expose it globally (like Node)
|
110
|
-
*/
|
111
|
-
export function symbol_metadata(arg: ClassLike): typeof Symbol.metadata {
|
112
|
-
const symbol_metadata =
|
113
|
-
Symbol.metadata || Object.getOwnPropertySymbols(arg).find(s => s.description == 'Symbol.metadata');
|
114
|
-
_polyfill_contextMetadata(arg);
|
115
|
-
if (!symbol_metadata) {
|
116
|
-
throw new ReferenceError('Could not get a reference to Symbol.metadata');
|
117
|
-
}
|
118
|
-
|
119
|
-
return symbol_metadata as typeof Symbol.metadata;
|
120
|
-
}
|
121
|
-
|
122
126
|
export function isStatic<T extends Metadata = Metadata>(arg: unknown): arg is Static<T> {
|
123
|
-
return (
|
124
|
-
typeof arg == 'function'
|
125
|
-
&& symbol_metadata(arg as ClassLike) in arg
|
126
|
-
&& isValidMetadata(arg[symbol_metadata(arg as ClassLike)])
|
127
|
-
);
|
127
|
+
return typeof arg == 'function' && Symbol.metadata in arg && isValidMetadata(arg[Symbol.metadata]);
|
128
128
|
}
|
129
129
|
|
130
130
|
export interface Instance<T extends Metadata = Metadata> {
|
@@ -176,8 +176,10 @@ export function isCustom(arg: unknown): arg is Custom {
|
|
176
176
|
|
177
177
|
export type Like<T extends Metadata = Metadata> = InstanceLike<T> | StaticLike<T>;
|
178
178
|
|
179
|
-
export type Size<T extends TypeLike> = T extends
|
180
|
-
?
|
181
|
-
: T extends
|
182
|
-
?
|
183
|
-
:
|
179
|
+
export type Size<T extends TypeLike> = T extends undefined | null
|
180
|
+
? 0
|
181
|
+
: T extends { readonly [Symbol.size]: infer S extends number }
|
182
|
+
? S
|
183
|
+
: T extends primitive.Valid
|
184
|
+
? primitive.Size<T>
|
185
|
+
: number;
|
package/src/struct.ts
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
import { toUint8Array } from './buffer.js';
|
2
|
+
import { _debugLog } from './debugging.js';
|
2
3
|
import * as primitive from './internal/primitives.js';
|
3
4
|
import type {
|
4
5
|
DecoratorContext,
|
@@ -10,45 +11,39 @@ import type {
|
|
10
11
|
Metadata,
|
11
12
|
Options,
|
12
13
|
Size,
|
13
|
-
Static,
|
14
14
|
StaticLike,
|
15
15
|
TypeLike,
|
16
16
|
} from './internal/struct.js';
|
17
|
-
import {
|
17
|
+
import {
|
18
|
+
_polyfill_metadata,
|
19
|
+
checkInstance,
|
20
|
+
checkStruct,
|
21
|
+
initMetadata,
|
22
|
+
isCustom,
|
23
|
+
isInstance,
|
24
|
+
isStatic,
|
25
|
+
} from './internal/struct.js';
|
18
26
|
import { _throw } from './misc.js';
|
19
27
|
import { capitalize } from './string.js';
|
20
28
|
import type { ClassLike } from './types.js';
|
21
29
|
export * as Struct from './internal/struct.js';
|
22
30
|
|
23
31
|
/**
|
24
|
-
* Gets the
|
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
|
32
|
+
* Gets the size in bytes of a type
|
27
33
|
*/
|
28
|
-
function
|
29
|
-
|
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);
|
34
|
+
export function sizeof<T extends TypeLike>(type: T | T[]): Size<T> {
|
35
|
+
if (type === undefined || type === null) return 0 as Size<T>;
|
40
36
|
|
41
|
-
|
37
|
+
if (Array.isArray(type)) {
|
38
|
+
let size = 0;
|
42
39
|
|
43
|
-
|
40
|
+
for (let i = 0; i < type.length; i++) {
|
41
|
+
size += sizeof(type[i]);
|
42
|
+
}
|
44
43
|
|
45
|
-
|
46
|
-
}
|
44
|
+
return size as Size<T>;
|
45
|
+
}
|
47
46
|
|
48
|
-
/**
|
49
|
-
* Gets the size in bytes of a type
|
50
|
-
*/
|
51
|
-
export function sizeof<T extends TypeLike>(type: T): Size<T> {
|
52
47
|
// primitive
|
53
48
|
if (typeof type == 'string') {
|
54
49
|
primitive.checkValid(type);
|
@@ -60,17 +55,19 @@ export function sizeof<T extends TypeLike>(type: T): Size<T> {
|
|
60
55
|
|
61
56
|
checkStruct(type);
|
62
57
|
|
63
|
-
const
|
64
|
-
|
65
|
-
|
58
|
+
const constructor = isStatic(type) ? type : type.constructor;
|
59
|
+
_polyfill_metadata(constructor);
|
60
|
+
const { struct } = constructor[Symbol.metadata];
|
66
61
|
|
67
62
|
if (isStatic(type)) return struct.staticSize as Size<T>;
|
68
63
|
|
69
64
|
let size = struct.staticSize;
|
70
65
|
|
71
|
-
for (const
|
72
|
-
if (typeof
|
73
|
-
|
66
|
+
for (const member of struct.members.values()) {
|
67
|
+
if (typeof member.length != 'string') continue;
|
68
|
+
for (let i = 0; i < (type as any)[member.length]; i++) {
|
69
|
+
size += sizeof((type as any)[member.name][i]);
|
70
|
+
}
|
74
71
|
}
|
75
72
|
|
76
73
|
return size as Size<T>;
|
@@ -82,12 +79,26 @@ export function sizeof<T extends TypeLike>(type: T): Size<T> {
|
|
82
79
|
export function offsetof(type: StaticLike | InstanceLike, memberName: string): number {
|
83
80
|
checkStruct(type);
|
84
81
|
|
85
|
-
const
|
86
|
-
|
82
|
+
const constructor = isStatic(type) ? type : type.constructor;
|
83
|
+
|
84
|
+
_polyfill_metadata(constructor);
|
85
|
+
const { struct } = constructor[Symbol.metadata];
|
87
86
|
|
88
|
-
|
89
|
-
|
90
|
-
|
87
|
+
if (isStatic(type) || !struct.isDynamic) {
|
88
|
+
return (
|
89
|
+
struct.members.get(memberName)?.staticOffset
|
90
|
+
?? _throw(new Error('Struct does not have member: ' + memberName))
|
91
|
+
);
|
92
|
+
}
|
93
|
+
|
94
|
+
let offset = 0;
|
95
|
+
|
96
|
+
for (const member of struct.members.values()) {
|
97
|
+
if (member.name == memberName) return offset;
|
98
|
+
offset += sizeof((type as any)[member.name]);
|
99
|
+
}
|
100
|
+
|
101
|
+
throw new Error('Struct does not have member: ' + memberName);
|
91
102
|
}
|
92
103
|
|
93
104
|
/**
|
@@ -105,26 +116,44 @@ export function struct(options: Partial<Options> = {}) {
|
|
105
116
|
target: T,
|
106
117
|
context: ClassDecoratorContext & DecoratorContext
|
107
118
|
): T {
|
108
|
-
context.metadata ??= {};
|
109
|
-
context.metadata.struct ??= {};
|
110
|
-
context.metadata.struct.init ??= [];
|
111
|
-
|
112
|
-
let staticSize = 0;
|
113
119
|
const members = new Map<string, Member>();
|
114
|
-
|
120
|
+
|
121
|
+
let staticSize = 0,
|
122
|
+
isDynamic = false;
|
123
|
+
|
124
|
+
for (const { name, type, length } of initMetadata(context)) {
|
115
125
|
if (!primitive.isValid(type) && !isStatic(type)) throw new TypeError('Not a valid type: ' + type);
|
116
126
|
|
127
|
+
if (typeof length == 'string') {
|
128
|
+
const countedBy = members.get(length);
|
129
|
+
|
130
|
+
if (!countedBy) throw new Error(`"${length}" is undefined or declared after "${name}"`);
|
131
|
+
|
132
|
+
if (!primitive.isType(countedBy.type))
|
133
|
+
throw new Error(`"${length}" is not a number and cannot be used to count "${name}"`);
|
134
|
+
}
|
135
|
+
|
136
|
+
let decl = `${typeof type == 'string' ? type : type.name} ${name}`;
|
137
|
+
|
138
|
+
if (length !== undefined) decl += `[${length}]`;
|
139
|
+
|
117
140
|
members.set(name, {
|
118
|
-
|
141
|
+
name,
|
142
|
+
staticOffset: options.isUnion ? 0 : staticSize,
|
119
143
|
type: primitive.isValid(type) ? primitive.normalize(type) : type,
|
120
144
|
length,
|
145
|
+
decl,
|
121
146
|
});
|
147
|
+
|
122
148
|
const memberSize = typeof length == 'string' ? 0 : sizeof(type) * (length || 1);
|
149
|
+
isDynamic ||= typeof length == 'string';
|
123
150
|
staticSize = options.isUnion ? Math.max(staticSize, memberSize) : staticSize + memberSize;
|
124
151
|
staticSize = align(staticSize, options.align || 1);
|
152
|
+
|
153
|
+
_debugLog('define', target.name + '.' + name);
|
125
154
|
}
|
126
155
|
|
127
|
-
context.metadata.struct = { options, members, staticSize } satisfies Metadata;
|
156
|
+
context.metadata.struct = { options, members, staticSize, isDynamic } satisfies Metadata;
|
128
157
|
|
129
158
|
return target;
|
130
159
|
};
|
@@ -143,14 +172,20 @@ export function member(type: primitive.Valid | ClassLike, length?: number | stri
|
|
143
172
|
|
144
173
|
if (!name) throw new ReferenceError('Invalid name for struct member');
|
145
174
|
|
146
|
-
context.
|
147
|
-
context.metadata.struct ??= {};
|
148
|
-
context.metadata.struct.init ??= [];
|
149
|
-
context.metadata.struct.init.push({ name, type, length } satisfies MemberInit);
|
175
|
+
initMetadata(context).push({ name, type, length } satisfies MemberInit);
|
150
176
|
return value;
|
151
177
|
};
|
152
178
|
}
|
153
179
|
|
180
|
+
/** Gets the length of a member */
|
181
|
+
function _memberLength<T extends Metadata>(instance: Instance<T>, member: Member): number {
|
182
|
+
if (member.length === undefined) return -1;
|
183
|
+
if (typeof member.length == 'string') return (instance as any)[member.length];
|
184
|
+
return Number.isSafeInteger(member.length) && member.length >= 0
|
185
|
+
? member.length
|
186
|
+
: _throw(new Error('Array lengths must be natural numbers'));
|
187
|
+
}
|
188
|
+
|
154
189
|
/**
|
155
190
|
* Serializes a struct into a Uint8Array
|
156
191
|
*/
|
@@ -158,58 +193,69 @@ export function serialize(instance: unknown): Uint8Array {
|
|
158
193
|
if (isCustom(instance) && typeof instance[Symbol.serialize] == 'function') return instance[Symbol.serialize]!();
|
159
194
|
|
160
195
|
checkInstance(instance);
|
161
|
-
|
196
|
+
_polyfill_metadata(instance.constructor);
|
197
|
+
const { options, members } = instance.constructor[Symbol.metadata].struct;
|
162
198
|
|
163
|
-
const
|
199
|
+
const size = sizeof(instance);
|
200
|
+
const buffer = new Uint8Array(size);
|
164
201
|
const view = new DataView(buffer.buffer);
|
165
202
|
|
203
|
+
_debugLog('serialize', instance.constructor.name);
|
204
|
+
|
205
|
+
let offset = 0,
|
206
|
+
nextOffset = 0;
|
207
|
+
|
166
208
|
// for unions we should write members in ascending last modified order, but we don't have that info.
|
167
|
-
for (const
|
168
|
-
const length = _memberLength(instance,
|
169
|
-
|
170
|
-
|
209
|
+
for (const member of members.values()) {
|
210
|
+
const length = _memberLength(instance, member);
|
211
|
+
|
212
|
+
_debugLog('\t', member.decl);
|
171
213
|
|
172
|
-
|
214
|
+
for (let i = 0; i < Math.abs(length); i++) {
|
215
|
+
let value = length != -1 ? instance[member.name][i] : instance[member.name];
|
173
216
|
if (typeof value == 'string') {
|
174
217
|
value = value.charCodeAt(0);
|
175
218
|
}
|
176
219
|
|
177
|
-
|
178
|
-
|
220
|
+
offset = nextOffset;
|
221
|
+
nextOffset += isInstance(value) ? sizeof(value) : sizeof(member.type);
|
222
|
+
|
223
|
+
if (!primitive.isType(member.type)) {
|
224
|
+
buffer.set(value ? serialize(value) : new Uint8Array(sizeof(member.type)), offset);
|
179
225
|
continue;
|
180
226
|
}
|
181
227
|
|
182
|
-
const fn = `set${capitalize(type)}` as const;
|
228
|
+
const fn = `set${capitalize(member.type)}` as const;
|
183
229
|
|
184
230
|
if (fn == 'setInt64') {
|
185
|
-
view.setBigInt64(
|
231
|
+
view.setBigInt64(offset, BigInt(value), !options.bigEndian);
|
186
232
|
continue;
|
187
233
|
}
|
188
234
|
|
189
235
|
if (fn == 'setUint64') {
|
190
|
-
view.setBigUint64(
|
236
|
+
view.setBigUint64(offset, BigInt(value), !options.bigEndian);
|
191
237
|
continue;
|
192
238
|
}
|
193
239
|
|
194
240
|
if (fn == 'setInt128') {
|
195
|
-
view.setBigUint64(
|
196
|
-
view.setBigInt64(
|
241
|
+
view.setBigUint64(offset + (!options.bigEndian ? 0 : 8), value & primitive.mask64, !options.bigEndian);
|
242
|
+
view.setBigInt64(offset + (!options.bigEndian ? 8 : 0), value >> BigInt(64), !options.bigEndian);
|
197
243
|
continue;
|
198
244
|
}
|
199
245
|
|
200
246
|
if (fn == 'setUint128') {
|
201
|
-
view.setBigUint64(
|
202
|
-
view.setBigUint64(
|
247
|
+
view.setBigUint64(offset + (!options.bigEndian ? 0 : 8), value & primitive.mask64, !options.bigEndian);
|
248
|
+
view.setBigUint64(offset + (!options.bigEndian ? 8 : 0), value >> BigInt(64), !options.bigEndian);
|
203
249
|
continue;
|
204
250
|
}
|
205
251
|
|
206
252
|
if (fn == 'setFloat128') {
|
207
|
-
view.setFloat64(
|
208
|
-
view.setBigUint64(
|
253
|
+
view.setFloat64(offset + (!options.bigEndian ? 0 : 8), Number(value), !options.bigEndian);
|
254
|
+
view.setBigUint64(offset + (!options.bigEndian ? 8 : 0), BigInt(0), !options.bigEndian);
|
209
255
|
continue;
|
210
256
|
}
|
211
257
|
|
212
|
-
view[fn](
|
258
|
+
view[fn](offset, Number(value), !options.bigEndian);
|
213
259
|
}
|
214
260
|
}
|
215
261
|
|
@@ -226,64 +272,77 @@ export function deserialize(instance: unknown, _buffer: ArrayBufferLike | ArrayB
|
|
226
272
|
return instance[Symbol.deserialize]!(buffer);
|
227
273
|
|
228
274
|
checkInstance(instance);
|
229
|
-
|
275
|
+
_polyfill_metadata(instance.constructor);
|
276
|
+
const { options, members } = instance.constructor[Symbol.metadata].struct;
|
230
277
|
|
231
278
|
const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
232
279
|
|
233
|
-
|
234
|
-
|
280
|
+
_debugLog('deserialize', instance.constructor.name);
|
281
|
+
|
282
|
+
let offset = 0,
|
283
|
+
nextOffset = 0;
|
284
|
+
|
285
|
+
for (const member of members.values()) {
|
286
|
+
const length = _memberLength(instance, member);
|
287
|
+
|
288
|
+
_debugLog('\t', member.decl);
|
289
|
+
|
235
290
|
for (let i = 0; i < Math.abs(length); i++) {
|
236
|
-
let object = length != -1 ? instance[name] : instance;
|
237
|
-
const key = length != -1 ? i : name
|
238
|
-
iOff = offset + sizeof(type) * i;
|
291
|
+
let object = length != -1 ? instance[member.name] : instance;
|
292
|
+
const key = length != -1 ? i : member.name;
|
239
293
|
|
240
|
-
|
241
|
-
|
242
|
-
|
294
|
+
offset = nextOffset;
|
295
|
+
if (!isInstance(object[key])) nextOffset += sizeof(member.type);
|
296
|
+
|
297
|
+
if (typeof instance[member.name] == 'string') {
|
298
|
+
instance[member.name] =
|
299
|
+
instance[member.name].slice(0, i)
|
300
|
+
+ String.fromCharCode(view.getUint8(offset))
|
301
|
+
+ instance[member.name].slice(i + 1);
|
243
302
|
continue;
|
244
303
|
}
|
245
304
|
|
246
|
-
if (!primitive.isType(type)) {
|
247
|
-
if (object[key] === null || object[key] === undefined)
|
248
|
-
|
249
|
-
|
250
|
-
|
305
|
+
if (!primitive.isType(member.type)) {
|
306
|
+
if (object[key] === null || object[key] === undefined) continue;
|
307
|
+
|
308
|
+
deserialize(object[key], new Uint8Array(buffer.subarray(offset)));
|
309
|
+
nextOffset += sizeof(object[key]);
|
251
310
|
continue;
|
252
311
|
}
|
253
312
|
|
254
313
|
if (length && length != -1) object ||= [];
|
255
314
|
|
256
|
-
const fn = `get${capitalize(type)}` as const;
|
315
|
+
const fn = `get${capitalize(member.type)}` as const;
|
257
316
|
if (fn == 'getInt64') {
|
258
|
-
object[key] = view.getBigInt64(
|
317
|
+
object[key] = view.getBigInt64(offset, !options.bigEndian);
|
259
318
|
continue;
|
260
319
|
}
|
261
320
|
|
262
321
|
if (fn == 'getUint64') {
|
263
|
-
object[key] = view.getBigUint64(
|
322
|
+
object[key] = view.getBigUint64(offset, !options.bigEndian);
|
264
323
|
continue;
|
265
324
|
}
|
266
325
|
|
267
326
|
if (fn == 'getInt128') {
|
268
327
|
object[key] =
|
269
|
-
(view.getBigInt64(
|
270
|
-
| view.getBigUint64(
|
328
|
+
(view.getBigInt64(offset + (!options.bigEndian ? 8 : 0), !options.bigEndian) << BigInt(64))
|
329
|
+
| view.getBigUint64(offset + (!options.bigEndian ? 0 : 8), !options.bigEndian);
|
271
330
|
continue;
|
272
331
|
}
|
273
332
|
|
274
333
|
if (fn == 'getUint128') {
|
275
334
|
object[key] =
|
276
|
-
(view.getBigUint64(
|
277
|
-
| view.getBigUint64(
|
335
|
+
(view.getBigUint64(offset + (!options.bigEndian ? 8 : 0), !options.bigEndian) << BigInt(64))
|
336
|
+
| view.getBigUint64(offset + (!options.bigEndian ? 0 : 8), !options.bigEndian);
|
278
337
|
continue;
|
279
338
|
}
|
280
339
|
|
281
340
|
if (fn == 'getFloat128') {
|
282
|
-
object[key] = view.getFloat64(
|
341
|
+
object[key] = view.getFloat64(offset + (!options.bigEndian ? 0 : 8), !options.bigEndian);
|
283
342
|
continue;
|
284
343
|
}
|
285
344
|
|
286
|
-
object[key] = view[fn](
|
345
|
+
object[key] = view[fn](offset, !options.bigEndian);
|
287
346
|
}
|
288
347
|
}
|
289
348
|
}
|