utilium 1.10.1 → 2.0.0-pre.2
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/buffer.d.ts +340 -1
- package/dist/buffer.js +58 -0
- package/dist/internal/primitives.d.ts +91 -18
- package/dist/internal/primitives.js +90 -25
- package/dist/internal/struct.d.ts +24 -49
- package/dist/internal/struct.js +7 -24
- package/dist/objects.d.ts +6 -0
- package/dist/struct.d.ts +18 -18
- package/dist/struct.js +123 -217
- package/package.json +1 -1
- package/src/buffer.ts +363 -1
- package/src/internal/primitives.ts +120 -46
- package/src/internal/struct.ts +41 -73
- package/src/objects.ts +7 -0
- package/src/struct.ts +157 -267
package/src/struct.ts
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
import {
|
1
|
+
import { BufferViewArray } from './buffer.js';
|
2
2
|
import { _debugLog } from './debugging.js';
|
3
3
|
import * as primitive from './internal/primitives.js';
|
4
4
|
import type {
|
@@ -6,27 +6,15 @@ import type {
|
|
6
6
|
Instance,
|
7
7
|
InstanceLike,
|
8
8
|
Member,
|
9
|
-
MemberContext,
|
10
|
-
MemberInit,
|
11
9
|
Metadata,
|
12
10
|
Options,
|
13
11
|
Size,
|
14
12
|
StaticLike,
|
15
13
|
TypeLike,
|
16
14
|
} from './internal/struct.js';
|
17
|
-
import {
|
18
|
-
_polyfill_metadata,
|
19
|
-
checkInstance,
|
20
|
-
checkStruct,
|
21
|
-
initMetadata,
|
22
|
-
isCustom,
|
23
|
-
isInstance,
|
24
|
-
isStatic,
|
25
|
-
isStruct,
|
26
|
-
} from './internal/struct.js';
|
15
|
+
import { checkStruct, initMetadata, isInstance, isStatic, isStruct } from './internal/struct.js';
|
27
16
|
import { _throw } from './misc.js';
|
28
|
-
import {
|
29
|
-
import type { ClassLike } from './types.js';
|
17
|
+
import { getAllPrototypes } from './objects.js';
|
30
18
|
export * as Struct from './internal/struct.js';
|
31
19
|
|
32
20
|
/**
|
@@ -49,43 +37,33 @@ export function sizeof<T extends TypeLike>(type: T | T[]): Size<T> {
|
|
49
37
|
if (typeof type == 'string') {
|
50
38
|
primitive.checkValid(type);
|
51
39
|
|
52
|
-
return
|
40
|
+
return primitive.types[primitive.normalize(type)].size as Size<T>;
|
53
41
|
}
|
54
42
|
|
55
|
-
if (
|
43
|
+
if (primitive.isType(type)) return type.size as Size<T>;
|
56
44
|
|
57
45
|
checkStruct(type);
|
58
46
|
|
59
47
|
const constructor = isStatic(type) ? type : type.constructor;
|
60
|
-
|
61
|
-
const { struct } = constructor[Symbol.metadata];
|
62
|
-
|
63
|
-
let size = struct.staticSize;
|
64
|
-
|
65
|
-
if (isStatic(type)) return size as Size<T>;
|
48
|
+
const { struct, structInit } = constructor[Symbol.metadata];
|
66
49
|
|
67
|
-
|
68
|
-
const value = (type as any)[member.name];
|
69
|
-
|
70
|
-
if (isInstance(value) && value.constructor[Symbol.metadata].struct.isDynamic) {
|
71
|
-
if (struct.isUnion) size = Math.max(size, sizeof(value));
|
72
|
-
else size += sizeof(value);
|
73
|
-
continue;
|
74
|
-
}
|
50
|
+
if (isStatic(type) || !struct.isDynamic) return struct.staticSize as Size<T>;
|
75
51
|
|
76
|
-
|
52
|
+
const last = structInit.members.at(-1)!;
|
53
|
+
const length = (type as any)[last.length as keyof typeof type];
|
54
|
+
let dynamicSize = 0;
|
77
55
|
|
78
|
-
|
56
|
+
if (primitive.isType(last.type)) {
|
57
|
+
dynamicSize = last.type.size * length;
|
58
|
+
} else {
|
59
|
+
const value = type[last.name];
|
79
60
|
|
80
|
-
for (let i = 0; i <
|
81
|
-
|
61
|
+
for (let i = 0; i < length; i++) {
|
62
|
+
dynamicSize += sizeof(isStruct(value[i]) ? value[i] : last.type);
|
82
63
|
}
|
83
|
-
|
84
|
-
if (struct.isUnion) size = Math.max(size, subSize);
|
85
|
-
else size += subSize;
|
86
64
|
}
|
87
65
|
|
88
|
-
return
|
66
|
+
return (struct.isUnion ? Math.max(struct.staticSize, dynamicSize) : struct.staticSize + dynamicSize) as Size<T>;
|
89
67
|
}
|
90
68
|
|
91
69
|
/**
|
@@ -96,31 +74,14 @@ export function offsetof(type: StaticLike | InstanceLike, memberName: string): n
|
|
96
74
|
|
97
75
|
const constructor = isStatic(type) ? type : type.constructor;
|
98
76
|
|
99
|
-
|
100
|
-
const { struct } = constructor[Symbol.metadata];
|
101
|
-
|
102
|
-
if (isStatic(type) || !struct.isDynamic) {
|
103
|
-
return (
|
104
|
-
struct.members.get(memberName)?.staticOffset
|
105
|
-
?? _throw(new Error('Struct does not have member: ' + memberName))
|
106
|
-
);
|
107
|
-
}
|
108
|
-
|
109
|
-
let offset = 0;
|
110
|
-
|
111
|
-
for (const member of struct.members.values()) {
|
112
|
-
if (member.name == memberName) return offset;
|
77
|
+
const member = constructor[Symbol.metadata].struct.members.get(memberName);
|
113
78
|
|
114
|
-
|
115
|
-
offset += sizeof(isStruct(value) ? value : member.type);
|
116
|
-
}
|
79
|
+
if (!member) throw new Error('Struct does not have member: ' + memberName);
|
117
80
|
|
118
|
-
|
81
|
+
return member.offset;
|
119
82
|
}
|
120
83
|
|
121
|
-
/**
|
122
|
-
* Aligns a number
|
123
|
-
*/
|
84
|
+
/** Aligns a number */
|
124
85
|
export function align(value: number, alignment: number): number {
|
125
86
|
return Math.ceil(value / alignment) * alignment;
|
126
87
|
}
|
@@ -129,68 +90,51 @@ export function align(value: number, alignment: number): number {
|
|
129
90
|
* Decorates a class as a struct
|
130
91
|
*/
|
131
92
|
export function struct(options: Partial<Options> = {}) {
|
132
|
-
return function _decorateStruct<
|
93
|
+
return function _decorateStruct<T extends StaticLike>(
|
133
94
|
target: T,
|
134
|
-
context: ClassDecoratorContext & DecoratorContext
|
135
|
-
):
|
136
|
-
const
|
137
|
-
|
138
|
-
let staticSize = 0,
|
139
|
-
isDynamic = false;
|
140
|
-
|
141
|
-
for (const { name, type, length } of initMetadata(context)) {
|
142
|
-
if (!primitive.isValid(type) && !isStatic(type)) throw new TypeError('Not a valid type: ' + type);
|
143
|
-
|
144
|
-
if (typeof length == 'string') {
|
145
|
-
const countedBy = members.get(length);
|
95
|
+
context: ClassDecoratorContext<T> & DecoratorContext
|
96
|
+
): void {
|
97
|
+
const init = initMetadata(context);
|
146
98
|
|
147
|
-
|
148
|
-
|
149
|
-
if (!primitive.isType(countedBy.type))
|
150
|
-
throw new Error(`"${length}" is not a number and cannot be used to count "${name}"`);
|
151
|
-
}
|
152
|
-
|
153
|
-
let decl = `${typeof type == 'string' ? type : type.name} ${name}`;
|
154
|
-
|
155
|
-
if (length !== undefined) decl += `[${length}]`;
|
156
|
-
|
157
|
-
members.set(name, {
|
158
|
-
name,
|
159
|
-
staticOffset: options.isUnion ? 0 : staticSize,
|
160
|
-
type: primitive.isValid(type) ? primitive.normalize(type) : type,
|
161
|
-
length,
|
162
|
-
decl,
|
163
|
-
});
|
99
|
+
const members = new Map<string, Member>();
|
164
100
|
|
165
|
-
|
166
|
-
|
167
|
-
? 0
|
168
|
-
: sizeof(type) * (length || 1);
|
101
|
+
for (const member of init.members) {
|
102
|
+
if (options.isUnion) member.offset = 0;
|
169
103
|
|
170
|
-
|
171
|
-
staticSize = options.isUnion ? Math.max(staticSize, memberSize) : staticSize + memberSize;
|
172
|
-
staticSize = align(staticSize, options.align || 1);
|
104
|
+
_debugLog('define', target.name + '.' + member.name);
|
173
105
|
|
174
|
-
|
106
|
+
members.set(member.name, member);
|
175
107
|
}
|
176
108
|
|
177
109
|
context.metadata.struct = {
|
178
110
|
options,
|
179
111
|
members,
|
180
|
-
staticSize,
|
181
|
-
isDynamic,
|
112
|
+
staticSize: init.size,
|
113
|
+
isDynamic: init.isDynamic,
|
182
114
|
isUnion: options.isUnion ?? false,
|
183
115
|
} satisfies Metadata;
|
184
|
-
|
185
|
-
return target;
|
186
116
|
};
|
187
117
|
}
|
188
118
|
|
119
|
+
export interface MemberOptions {
|
120
|
+
bigEndian?: boolean;
|
121
|
+
length?: number;
|
122
|
+
align?: number;
|
123
|
+
typeName?: string;
|
124
|
+
countedBy?: string;
|
125
|
+
}
|
126
|
+
|
189
127
|
/**
|
190
128
|
* Decorates a class member to be serialized
|
191
129
|
*/
|
192
|
-
export function member(type: primitive.
|
193
|
-
return function
|
130
|
+
export function member<V>(type: primitive.Type | StaticLike, opt: MemberOptions = {}) {
|
131
|
+
return function __decorateMember(value: Target<V>, context: Context<V>): Result<V> {
|
132
|
+
if (context.kind != 'accessor') throw new Error('Member must be an accessor');
|
133
|
+
|
134
|
+
const init = initMetadata(context);
|
135
|
+
|
136
|
+
if (init.isDynamic) throw new Error('Dynamic members must be declared at the end of the struct');
|
137
|
+
|
194
138
|
let name = context.name;
|
195
139
|
if (typeof name == 'symbol') {
|
196
140
|
console.warn('Symbol used for struct member name will be coerced to string: ' + name.toString());
|
@@ -199,199 +143,145 @@ export function member(type: primitive.Valid | ClassLike, length?: number | stri
|
|
199
143
|
|
200
144
|
if (!name) throw new ReferenceError('Invalid name for struct member');
|
201
145
|
|
202
|
-
|
203
|
-
return value;
|
204
|
-
};
|
205
|
-
}
|
146
|
+
if (!primitive.isType(type) && !isStatic(type)) throw new TypeError('Not a valid type: ' + type.name);
|
206
147
|
|
207
|
-
|
208
|
-
|
209
|
-
if (member.length === undefined) return -1;
|
210
|
-
if (typeof member.length == 'string') return (instance as any)[member.length];
|
211
|
-
return Number.isSafeInteger(member.length) && member.length >= 0
|
212
|
-
? member.length
|
213
|
-
: _throw(new Error('Array lengths must be natural numbers'));
|
214
|
-
}
|
148
|
+
if (typeof opt.length == 'string') {
|
149
|
+
const countedBy = init.members.find(m => m.name == opt.countedBy);
|
215
150
|
|
216
|
-
|
217
|
-
* Serializes a struct into a Uint8Array
|
218
|
-
*/
|
219
|
-
export function serialize(instance: unknown): Uint8Array {
|
220
|
-
if (isCustom(instance) && typeof instance[Symbol.serialize] == 'function') return instance[Symbol.serialize]!();
|
151
|
+
if (!countedBy) throw new Error(`"${opt.countedBy}" is not declared and cannot be used to count "${name}"`);
|
221
152
|
|
222
|
-
|
223
|
-
|
224
|
-
const { options, members } = instance.constructor[Symbol.metadata].struct;
|
153
|
+
if (!primitive.isType(countedBy.type))
|
154
|
+
throw new Error(`"${opt.countedBy}" is not a number and cannot be used to count "${name}"`);
|
225
155
|
|
226
|
-
|
227
|
-
|
228
|
-
const view = new DataView(buffer.buffer);
|
156
|
+
init.isDynamic = true;
|
157
|
+
}
|
229
158
|
|
230
|
-
|
159
|
+
const size = align(
|
160
|
+
sizeof(type) * (typeof opt.length == 'string' ? 0 : (opt.length ?? 1)),
|
161
|
+
opt.align ?? sizeof(type)
|
162
|
+
);
|
231
163
|
|
232
|
-
|
233
|
-
|
164
|
+
const member = {
|
165
|
+
name,
|
166
|
+
offset: init.size,
|
167
|
+
type,
|
168
|
+
length: opt.length,
|
169
|
+
countedBy: opt.countedBy,
|
170
|
+
size,
|
171
|
+
decl: `${opt.typeName ?? type.name} ${name}${opt.length !== undefined ? `[${JSON.stringify(opt.length)}]` : ''}`,
|
172
|
+
littleEndian: !opt.bigEndian,
|
173
|
+
} satisfies Member;
|
174
|
+
|
175
|
+
init.members.push(member);
|
176
|
+
|
177
|
+
// Apply after setting `offset`
|
178
|
+
init.size += size;
|
179
|
+
|
180
|
+
return {
|
181
|
+
get() {
|
182
|
+
return _get(this, member);
|
183
|
+
},
|
184
|
+
set(value) {
|
185
|
+
_set(this, member, value);
|
186
|
+
},
|
187
|
+
};
|
188
|
+
};
|
189
|
+
}
|
234
190
|
|
235
|
-
|
236
|
-
|
237
|
-
|
191
|
+
/** Gets the length of a member */
|
192
|
+
function _memberLength<T extends Metadata>(instance: Instance<T>, length?: number, countedBy?: string): number {
|
193
|
+
if (length === undefined) return -1;
|
194
|
+
if (typeof countedBy == 'string') length = Math.min(length, instance[countedBy]);
|
195
|
+
return Number.isSafeInteger(length) && length >= 0
|
196
|
+
? length
|
197
|
+
: _throw(new Error('Array lengths must be natural numbers'));
|
198
|
+
}
|
238
199
|
|
239
|
-
|
200
|
+
function _set(instance: Instance, member: Member, value: any, index?: number) {
|
201
|
+
const { name, type, length: maxLength, countedBy } = member;
|
202
|
+
const length = _memberLength(instance, maxLength, countedBy);
|
240
203
|
|
241
|
-
|
242
|
-
|
243
|
-
if (typeof value == 'string') {
|
244
|
-
value = value.charCodeAt(0);
|
245
|
-
}
|
204
|
+
if (!primitive.isType(type)) {
|
205
|
+
if (!isInstance(value)) return _debugLog(`Tried to set "${name}" to a non-instance value`);
|
246
206
|
|
247
|
-
|
248
|
-
|
207
|
+
if (length > 0 && typeof index != 'number') {
|
208
|
+
for (let i = 0; i < length; i++) _set(instance, member, value[i], i);
|
209
|
+
return;
|
210
|
+
}
|
249
211
|
|
250
|
-
|
251
|
-
|
252
|
-
continue;
|
253
|
-
}
|
212
|
+
if (!Array.from(getAllPrototypes(value.constructor)).some(c => c === type))
|
213
|
+
throw new Error(`${value.constructor.name} is not a subtype of ${type.name}`);
|
254
214
|
|
255
|
-
|
215
|
+
const offset = instance.byteOffset + member.offset + (index ?? 0) * sizeof(type);
|
256
216
|
|
257
|
-
|
258
|
-
|
259
|
-
continue;
|
260
|
-
}
|
217
|
+
// It's already the same value
|
218
|
+
if (value.buffer === instance.buffer && value.byteOffset === offset) return;
|
261
219
|
|
262
|
-
|
263
|
-
view.setBigUint64(offset, BigInt(value), !options.bigEndian);
|
264
|
-
continue;
|
265
|
-
}
|
220
|
+
const current = new Uint8Array(instance.buffer, offset, sizeof(value));
|
266
221
|
|
267
|
-
|
268
|
-
view.setBigUint64(offset + (!options.bigEndian ? 0 : 8), value & primitive.mask64, !options.bigEndian);
|
269
|
-
view.setBigInt64(offset + (!options.bigEndian ? 8 : 0), value >> BigInt(64), !options.bigEndian);
|
270
|
-
continue;
|
271
|
-
}
|
222
|
+
current.set(new Uint8Array(value.buffer, value.byteOffset, sizeof(value)));
|
272
223
|
|
273
|
-
|
274
|
-
|
275
|
-
view.setBigUint64(offset + (!options.bigEndian ? 8 : 0), value >> BigInt(64), !options.bigEndian);
|
276
|
-
continue;
|
277
|
-
}
|
224
|
+
return;
|
225
|
+
}
|
278
226
|
|
279
|
-
|
280
|
-
view.setFloat64(offset + (!options.bigEndian ? 0 : 8), Number(value), !options.bigEndian);
|
281
|
-
view.setBigUint64(offset + (!options.bigEndian ? 8 : 0), BigInt(0), !options.bigEndian);
|
282
|
-
continue;
|
283
|
-
}
|
227
|
+
const view = new DataView(instance.buffer, instance.byteOffset, instance.byteLength);
|
284
228
|
|
285
|
-
|
229
|
+
if (length > 0 && typeof index != 'number') {
|
230
|
+
for (let i = 0; i < length; i++) {
|
231
|
+
const offset = member.offset + i * type.size;
|
232
|
+
type.set(view, offset, member.littleEndian, value[i]);
|
286
233
|
}
|
234
|
+
return;
|
287
235
|
}
|
288
236
|
|
289
|
-
|
290
|
-
}
|
291
|
-
|
292
|
-
/**
|
293
|
-
* Deserializes a struct from a Uint8Array
|
294
|
-
*/
|
295
|
-
export function deserialize(instance: unknown, _buffer: ArrayBufferLike | ArrayBufferView) {
|
296
|
-
const buffer = toUint8Array(_buffer);
|
297
|
-
|
298
|
-
if (isCustom(instance) && typeof instance[Symbol.deserialize] == 'function')
|
299
|
-
return instance[Symbol.deserialize]!(buffer);
|
300
|
-
|
301
|
-
checkInstance(instance);
|
302
|
-
_polyfill_metadata(instance.constructor);
|
303
|
-
const { options, members } = instance.constructor[Symbol.metadata].struct;
|
304
|
-
|
305
|
-
const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
306
|
-
|
307
|
-
_debugLog('deserialize', instance.constructor.name);
|
308
|
-
|
309
|
-
let offset = 0,
|
310
|
-
nextOffset = 0;
|
237
|
+
if (typeof value == 'string') value = value.charCodeAt(0);
|
311
238
|
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
_debugLog('\t', member.decl);
|
316
|
-
|
317
|
-
for (let i = 0; i < Math.abs(length); i++) {
|
318
|
-
let object = length != -1 ? instance[member.name] : instance;
|
319
|
-
const key = length != -1 ? i : member.name;
|
320
|
-
|
321
|
-
const isNullish = object[key] === null || object[key] === undefined;
|
322
|
-
|
323
|
-
const needsAllocation = isNullish && isStatic(member.type) && member.type[Symbol.metadata].struct.isDynamic;
|
324
|
-
|
325
|
-
offset = nextOffset;
|
326
|
-
if (!isInstance(object[key]) && !needsAllocation) nextOffset += sizeof(member.type);
|
327
|
-
|
328
|
-
if (typeof instance[member.name] == 'string') {
|
329
|
-
instance[member.name] =
|
330
|
-
instance[member.name].slice(0, i)
|
331
|
-
+ String.fromCharCode(view.getUint8(offset))
|
332
|
-
+ instance[member.name].slice(i + 1);
|
333
|
-
continue;
|
334
|
-
}
|
335
|
-
|
336
|
-
if (!primitive.isType(member.type)) {
|
337
|
-
if (needsAllocation && isStatic(member.type)) object[key] ??= new member.type();
|
338
|
-
else if (isNullish) continue;
|
339
|
-
|
340
|
-
deserialize(object[key], new Uint8Array(buffer.subarray(offset)));
|
341
|
-
nextOffset += sizeof(object[key]);
|
342
|
-
continue;
|
343
|
-
}
|
344
|
-
|
345
|
-
if (length && length != -1) object ||= [];
|
346
|
-
|
347
|
-
const fn = `get${capitalize(member.type)}` as const;
|
348
|
-
if (fn == 'getInt64') {
|
349
|
-
object[key] = view.getBigInt64(offset, !options.bigEndian);
|
350
|
-
continue;
|
351
|
-
}
|
239
|
+
type.set(view, member.offset + (index ?? 0) * type.size, member.littleEndian, value);
|
240
|
+
}
|
352
241
|
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
}
|
242
|
+
function _get(instance: Instance, member: Member, index?: number) {
|
243
|
+
const { type, length: maxLength, countedBy } = member;
|
244
|
+
const length = _memberLength(instance, maxLength, countedBy);
|
357
245
|
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
246
|
+
if (length > 0 && typeof index != 'number') {
|
247
|
+
return new (primitive.isType(type) ? type.array : BufferViewArray(type, sizeof(type)))(
|
248
|
+
instance.buffer,
|
249
|
+
instance.byteOffset + member.offset,
|
250
|
+
length * sizeof(type)
|
251
|
+
);
|
252
|
+
}
|
364
253
|
|
365
|
-
|
366
|
-
object[key] =
|
367
|
-
(view.getBigUint64(offset + (!options.bigEndian ? 8 : 0), !options.bigEndian) << BigInt(64))
|
368
|
-
| view.getBigUint64(offset + (!options.bigEndian ? 0 : 8), !options.bigEndian);
|
369
|
-
continue;
|
370
|
-
}
|
254
|
+
const offset = member.offset + (index ?? 0) * sizeof(type);
|
371
255
|
|
372
|
-
|
373
|
-
object[key] = view.getFloat64(offset + (!options.bigEndian ? 0 : 8), !options.bigEndian);
|
374
|
-
continue;
|
375
|
-
}
|
256
|
+
if (isStatic(type)) return new type(instance.buffer, offset, sizeof(type));
|
376
257
|
|
377
|
-
|
378
|
-
|
379
|
-
}
|
258
|
+
const view = new DataView(instance.buffer, instance.byteOffset, instance.byteLength);
|
259
|
+
return type.get(view, offset, member.littleEndian);
|
380
260
|
}
|
381
261
|
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
262
|
+
// Decorator utility types
|
263
|
+
type Target<V> = ClassAccessorDecoratorTarget<any, V>;
|
264
|
+
type Result<V> = ClassAccessorDecoratorResult<any, V>;
|
265
|
+
type Context<V> = ClassAccessorDecoratorContext<any, V> & DecoratorContext;
|
266
|
+
type Decorator<V> = (value: Target<V>, context: Context<V>) => Result<V>;
|
267
|
+
|
268
|
+
function _member<T extends primitive.Valid>(typeName: T) {
|
269
|
+
const type = primitive.types[primitive.normalize(typeName)];
|
270
|
+
|
271
|
+
function _structMemberDecorator<V>(length: number, options?: Omit<MemberOptions, 'length'>): Decorator<V>;
|
272
|
+
function _structMemberDecorator<V>(value: Target<V>, context: Context<V>): Result<V>;
|
273
|
+
function _structMemberDecorator<V>(
|
274
|
+
valueOrLength: Target<V> | number,
|
275
|
+
context?: Context<V> | Omit<MemberOptions, 'length'>
|
276
|
+
): Decorator<V> | Result<V> {
|
277
|
+
return typeof valueOrLength == 'number'
|
278
|
+
? member<V>(type, { typeName, length: valueOrLength, ...context })
|
279
|
+
: member<V>(type, { typeName })(
|
280
|
+
valueOrLength,
|
281
|
+
context && 'name' in context ? context : _throw('Invalid decorator context object')
|
282
|
+
);
|
394
283
|
}
|
284
|
+
|
395
285
|
return _structMemberDecorator;
|
396
286
|
}
|
397
287
|
|