utilium 0.5.10 → 0.6.1
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/{internal → src/internal}/struct.d.ts +21 -7
- package/dist/src/internal/struct.js +24 -0
- package/dist/{struct.d.ts → src/struct.d.ts} +8 -12
- package/dist/{struct.js → src/struct.js} +29 -31
- package/dist/test/struct-test.d.ts +1 -0
- package/dist/test/struct-test.js +188 -0
- package/package.json +1 -1
- package/src/internal/struct.ts +40 -12
- package/src/struct.ts +49 -44
- package/tsconfig.json +1 -2
- package/dist/internal/struct.js +0 -11
- /package/dist/{fs.d.ts → src/fs.d.ts} +0 -0
- /package/dist/{fs.js → src/fs.js} +0 -0
- /package/dist/{index.d.ts → src/index.d.ts} +0 -0
- /package/dist/{index.js → src/index.js} +0 -0
- /package/dist/{internal → src/internal}/primitives.d.ts +0 -0
- /package/dist/{internal → src/internal}/primitives.js +0 -0
- /package/dist/{list.d.ts → src/list.d.ts} +0 -0
- /package/dist/{list.js → src/list.js} +0 -0
- /package/dist/{misc.d.ts → src/misc.d.ts} +0 -0
- /package/dist/{misc.js → src/misc.js} +0 -0
- /package/dist/{numbers.d.ts → src/numbers.d.ts} +0 -0
- /package/dist/{numbers.js → src/numbers.js} +0 -0
- /package/dist/{objects.d.ts → src/objects.d.ts} +0 -0
- /package/dist/{objects.js → src/objects.js} +0 -0
- /package/dist/{random.d.ts → src/random.d.ts} +0 -0
- /package/dist/{random.js → src/random.js} +0 -0
- /package/dist/{string.d.ts → src/string.d.ts} +0 -0
- /package/dist/{string.js → src/string.js} +0 -0
- /package/dist/{types.d.ts → src/types.d.ts} +0 -0
- /package/dist/{types.js → src/types.js} +0 -0
@@ -6,7 +6,6 @@ export interface MemberInit {
|
|
6
6
|
length?: number;
|
7
7
|
}
|
8
8
|
export declare const init: unique symbol;
|
9
|
-
export type init = typeof init;
|
10
9
|
/**
|
11
10
|
* Options for struct initialization
|
12
11
|
*/
|
@@ -25,16 +24,31 @@ export interface Metadata {
|
|
25
24
|
size: number;
|
26
25
|
}
|
27
26
|
export declare const metadata: unique symbol;
|
28
|
-
export
|
27
|
+
export interface _DecoratorMetadata<T extends Metadata = Metadata> extends DecoratorMetadata {
|
28
|
+
[metadata]?: T;
|
29
|
+
[init]?: MemberInit[];
|
30
|
+
}
|
31
|
+
export interface DecoratorContext<T extends Metadata = Metadata> {
|
32
|
+
metadata: _DecoratorMetadata<T>;
|
33
|
+
}
|
34
|
+
export type MemberContext = ClassMemberDecoratorContext & DecoratorContext;
|
29
35
|
export interface Static<T extends Metadata = Metadata> {
|
30
|
-
[metadata]:
|
31
|
-
|
32
|
-
|
36
|
+
[Symbol.metadata]: DecoratorMetadata & {
|
37
|
+
[metadata]: T;
|
38
|
+
};
|
39
|
+
new (): Instance<T>;
|
40
|
+
prototype: Instance<T>;
|
33
41
|
}
|
34
42
|
export interface StaticLike<T extends Metadata = Metadata> extends ClassLike {
|
35
|
-
[metadata]?: T;
|
36
|
-
[init]?: MemberInit[];
|
43
|
+
[Symbol.metadata]?: _DecoratorMetadata<T> | null;
|
37
44
|
}
|
45
|
+
export declare function isValidMetadata<T extends Metadata = Metadata>(arg: unknown): arg is DecoratorMetadata & {
|
46
|
+
[metadata]: T;
|
47
|
+
};
|
48
|
+
/**
|
49
|
+
* Gets a reference to Symbol.metadata, even on platforms that do not expose it globally (like Node)
|
50
|
+
*/
|
51
|
+
export declare function symbol_metadata(arg: ClassLike): typeof Symbol.metadata;
|
38
52
|
export declare function isStatic<T extends Metadata = Metadata>(arg: unknown): arg is Static<T>;
|
39
53
|
export interface Instance<T extends Metadata = Metadata> {
|
40
54
|
constructor: Static<T>;
|
@@ -0,0 +1,24 @@
|
|
1
|
+
export const init = Symbol('struct_init');
|
2
|
+
export const metadata = Symbol('struct');
|
3
|
+
export function isValidMetadata(arg) {
|
4
|
+
return arg != null && typeof arg == 'object' && metadata in arg;
|
5
|
+
}
|
6
|
+
/**
|
7
|
+
* Gets a reference to Symbol.metadata, even on platforms that do not expose it globally (like Node)
|
8
|
+
*/
|
9
|
+
export function symbol_metadata(arg) {
|
10
|
+
const symbol_metadata = Symbol.metadata || Object.getOwnPropertySymbols(arg).find(s => s.description == 'Symbol.metadata');
|
11
|
+
if (!symbol_metadata) {
|
12
|
+
throw new ReferenceError('Could not get a reference to Symbol.metadata');
|
13
|
+
}
|
14
|
+
return symbol_metadata;
|
15
|
+
}
|
16
|
+
export function isStatic(arg) {
|
17
|
+
return typeof arg == 'function' && symbol_metadata(arg) in arg && isValidMetadata(arg[symbol_metadata(arg)]);
|
18
|
+
}
|
19
|
+
export function isInstance(arg) {
|
20
|
+
return arg != null && typeof arg == 'object' && isStatic(arg.constructor);
|
21
|
+
}
|
22
|
+
export function isStruct(arg) {
|
23
|
+
return isInstance(arg) || isStatic(arg);
|
24
|
+
}
|
@@ -1,11 +1,11 @@
|
|
1
|
-
import * as Struct from './internal/struct.js';
|
2
|
-
import { ClassLike } from './types.js';
|
3
1
|
import * as primitive from './internal/primitives.js';
|
4
|
-
|
2
|
+
import { DecoratorContext, InstanceLike, Options, Size, StaticLike, type MemberContext } from './internal/struct.js';
|
3
|
+
import { ClassLike } from './types.js';
|
4
|
+
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 primitive.Valid |
|
8
|
+
export declare function sizeof<T extends primitive.Valid | StaticLike | InstanceLike>(type: T): Size<T>;
|
9
9
|
/**
|
10
10
|
* Aligns a number
|
11
11
|
*/
|
@@ -13,11 +13,11 @@ export declare function align(value: number, alignment: number): number;
|
|
13
13
|
/**
|
14
14
|
* Decorates a class as a struct
|
15
15
|
*/
|
16
|
-
export declare function struct(options?: Partial<
|
16
|
+
export declare function struct(options?: Partial<Options>): <const T extends StaticLike>(target: T, context: ClassDecoratorContext & DecoratorContext) => T;
|
17
17
|
/**
|
18
18
|
* Decorates a class member to be serialized
|
19
19
|
*/
|
20
|
-
export declare function member(type: primitive.Valid | ClassLike, length?: number): (
|
20
|
+
export declare function member(type: primitive.Valid | ClassLike, length?: number): <V>(value: V, context: MemberContext) => V;
|
21
21
|
/**
|
22
22
|
* Serializes a struct into a Uint8Array
|
23
23
|
*/
|
@@ -26,13 +26,9 @@ export declare function serialize(instance: unknown): Uint8Array;
|
|
26
26
|
* Deserializes a struct from a Uint8Array
|
27
27
|
*/
|
28
28
|
export declare function deserialize(instance: unknown, _buffer: ArrayBuffer | ArrayBufferView): void;
|
29
|
-
/**
|
30
|
-
* Also can be a name when legacy decorators are used
|
31
|
-
*/
|
32
|
-
type Context = string | symbol | ClassMemberDecoratorContext;
|
33
29
|
declare function _member<T extends primitive.Valid>(type: T): {
|
34
|
-
(length: number): (
|
35
|
-
(
|
30
|
+
<const V>(length: number): (value: V, context: MemberContext) => V;
|
31
|
+
<const V>(value: V, context: MemberContext): V;
|
36
32
|
};
|
37
33
|
/**
|
38
34
|
* Shortcut types
|
@@ -1,7 +1,7 @@
|
|
1
|
-
import * as Struct from './internal/struct.js';
|
2
|
-
import { capitalize } from './string.js';
|
3
1
|
import * as primitive from './internal/primitives.js';
|
4
|
-
|
2
|
+
import { symbol_metadata, init, isInstance, isStatic, isStruct, metadata, } from './internal/struct.js';
|
3
|
+
import { capitalize } from './string.js';
|
4
|
+
export * as Struct from './internal/struct.js';
|
5
5
|
/**
|
6
6
|
* Gets the size in bytes of a type
|
7
7
|
*/
|
@@ -13,11 +13,11 @@ export function sizeof(type) {
|
|
13
13
|
}
|
14
14
|
return (+primitive.normalize(type).match(primitive.regex)[2] / 8);
|
15
15
|
}
|
16
|
-
if (!
|
16
|
+
if (!isStruct(type)) {
|
17
17
|
throw new TypeError('Not a struct');
|
18
18
|
}
|
19
|
-
const
|
20
|
-
return
|
19
|
+
const struct = isStatic(type) ? type : type.constructor;
|
20
|
+
return struct[symbol_metadata(struct)][metadata].size;
|
21
21
|
}
|
22
22
|
/**
|
23
23
|
* Aligns a number
|
@@ -30,12 +30,14 @@ export function align(value, alignment) {
|
|
30
30
|
*/
|
31
31
|
export function struct(options = {}) {
|
32
32
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
33
|
-
return function (target,
|
34
|
-
|
33
|
+
return function __decorateStruct(target, context) {
|
34
|
+
context.metadata ??= {};
|
35
|
+
context.metadata[init] ||= [];
|
35
36
|
let size = 0;
|
36
37
|
const members = new Map();
|
37
|
-
for (const
|
38
|
-
|
38
|
+
for (const _ of context.metadata[init]) {
|
39
|
+
const { name, type, length } = _;
|
40
|
+
if (!primitive.isValid(type) && !isStatic(type)) {
|
39
41
|
throw new TypeError('Not a valid type: ' + type);
|
40
42
|
}
|
41
43
|
members.set(name, {
|
@@ -46,15 +48,16 @@ export function struct(options = {}) {
|
|
46
48
|
size += sizeof(type) * (length || 1);
|
47
49
|
size = align(size, options.align || 1);
|
48
50
|
}
|
49
|
-
|
51
|
+
context.metadata[metadata] = { options, members, size };
|
52
|
+
return target;
|
50
53
|
};
|
51
54
|
}
|
52
55
|
/**
|
53
56
|
* Decorates a class member to be serialized
|
54
57
|
*/
|
55
58
|
export function member(type, length) {
|
56
|
-
return function (
|
57
|
-
let name =
|
59
|
+
return function (value, context) {
|
60
|
+
let name = context.name;
|
58
61
|
if (typeof name == 'symbol') {
|
59
62
|
console.warn('Symbol used for struct member name will be coerced to string: ' + name.toString());
|
60
63
|
name = name.toString();
|
@@ -62,25 +65,20 @@ export function member(type, length) {
|
|
62
65
|
if (!name) {
|
63
66
|
throw new ReferenceError('Invalid name for struct member');
|
64
67
|
}
|
65
|
-
|
66
|
-
|
67
|
-
}
|
68
|
-
|
69
|
-
throw new TypeError('Invalid member for struct field');
|
70
|
-
}
|
71
|
-
const struct = target.constructor;
|
72
|
-
struct[Struct.init] ||= [];
|
73
|
-
struct[Struct.init].push({ name, type, length });
|
68
|
+
context.metadata ??= {};
|
69
|
+
context.metadata[init] ||= [];
|
70
|
+
context.metadata[init].push({ name, type, length });
|
71
|
+
return value;
|
74
72
|
};
|
75
73
|
}
|
76
74
|
/**
|
77
75
|
* Serializes a struct into a Uint8Array
|
78
76
|
*/
|
79
77
|
export function serialize(instance) {
|
80
|
-
if (!
|
78
|
+
if (!isInstance(instance)) {
|
81
79
|
throw new TypeError('Can not serialize, not a struct instance');
|
82
80
|
}
|
83
|
-
const { options, members } = instance.constructor[
|
81
|
+
const { options, members } = instance.constructor[symbol_metadata(instance.constructor)][metadata];
|
84
82
|
const buffer = new Uint8Array(sizeof(instance));
|
85
83
|
const view = new DataView(buffer.buffer);
|
86
84
|
for (const [name, { type, length, offset }] of members) {
|
@@ -114,10 +112,10 @@ export function serialize(instance) {
|
|
114
112
|
* Deserializes a struct from a Uint8Array
|
115
113
|
*/
|
116
114
|
export function deserialize(instance, _buffer) {
|
117
|
-
if (!
|
115
|
+
if (!isInstance(instance)) {
|
118
116
|
throw new TypeError('Can not deserialize, not a struct instance');
|
119
117
|
}
|
120
|
-
const { options, members } = instance.constructor[
|
118
|
+
const { options, members } = instance.constructor[symbol_metadata(instance.constructor)][metadata];
|
121
119
|
const buffer = new Uint8Array('buffer' in _buffer ? _buffer.buffer : _buffer);
|
122
120
|
const view = new DataView(buffer.buffer);
|
123
121
|
for (const [name, { type, offset, length }] of members) {
|
@@ -156,13 +154,13 @@ export function deserialize(instance, _buffer) {
|
|
156
154
|
}
|
157
155
|
}
|
158
156
|
function _member(type) {
|
159
|
-
function
|
160
|
-
if (typeof
|
161
|
-
return member(type,
|
157
|
+
function _structMemberDecorator(valueOrLength, context) {
|
158
|
+
if (typeof valueOrLength == 'number') {
|
159
|
+
return member(type, valueOrLength);
|
162
160
|
}
|
163
|
-
return member(type)(
|
161
|
+
return member(type)(valueOrLength, context);
|
164
162
|
}
|
165
|
-
return
|
163
|
+
return _structMemberDecorator;
|
166
164
|
}
|
167
165
|
/**
|
168
166
|
* Shortcut types
|
@@ -0,0 +1 @@
|
|
1
|
+
export {};
|
@@ -0,0 +1,188 @@
|
|
1
|
+
var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
|
2
|
+
function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
|
3
|
+
var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
|
4
|
+
var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
|
5
|
+
var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
|
6
|
+
var _, done = false;
|
7
|
+
for (var i = decorators.length - 1; i >= 0; i--) {
|
8
|
+
var context = {};
|
9
|
+
for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
|
10
|
+
for (var p in contextIn.access) context.access[p] = contextIn.access[p];
|
11
|
+
context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
|
12
|
+
var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
|
13
|
+
if (kind === "accessor") {
|
14
|
+
if (result === void 0) continue;
|
15
|
+
if (result === null || typeof result !== "object") throw new TypeError("Object expected");
|
16
|
+
if (_ = accept(result.get)) descriptor.get = _;
|
17
|
+
if (_ = accept(result.set)) descriptor.set = _;
|
18
|
+
if (_ = accept(result.init)) initializers.unshift(_);
|
19
|
+
}
|
20
|
+
else if (_ = accept(result)) {
|
21
|
+
if (kind === "field") initializers.unshift(_);
|
22
|
+
else descriptor[key] = _;
|
23
|
+
}
|
24
|
+
}
|
25
|
+
if (target) Object.defineProperty(target, contextIn.name, descriptor);
|
26
|
+
done = true;
|
27
|
+
};
|
28
|
+
var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
|
29
|
+
var useValue = arguments.length > 2;
|
30
|
+
for (var i = 0; i < initializers.length; i++) {
|
31
|
+
value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
|
32
|
+
}
|
33
|
+
return useValue ? value : void 0;
|
34
|
+
};
|
35
|
+
import { writeFileSync } from 'fs';
|
36
|
+
import { deserialize, member, serialize, struct, types as t } from '../src/struct.js';
|
37
|
+
import { join } from 'path';
|
38
|
+
let Header = (() => {
|
39
|
+
var _a;
|
40
|
+
let _classDecorators = [struct()];
|
41
|
+
let _classDescriptor;
|
42
|
+
let _classExtraInitializers = [];
|
43
|
+
let _classThis;
|
44
|
+
let _magic_start_decorators;
|
45
|
+
let _magic_start_initializers = [];
|
46
|
+
let _magic_start_extraInitializers = [];
|
47
|
+
let _segments_decorators;
|
48
|
+
let _segments_initializers = [];
|
49
|
+
let _segments_extraInitializers = [];
|
50
|
+
let _magic_end_decorators;
|
51
|
+
let _magic_end_initializers = [];
|
52
|
+
let _magic_end_extraInitializers = [];
|
53
|
+
var Header = class {
|
54
|
+
static { _classThis = this; }
|
55
|
+
static {
|
56
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
|
57
|
+
_magic_start_decorators = [t.char(4)];
|
58
|
+
_segments_decorators = [(_a = t).uint16.bind(_a)];
|
59
|
+
_magic_end_decorators = [t.char(4)];
|
60
|
+
__esDecorate(null, null, _magic_start_decorators, { kind: "field", name: "magic_start", static: false, private: false, access: { has: obj => "magic_start" in obj, get: obj => obj.magic_start, set: (obj, value) => { obj.magic_start = value; } }, metadata: _metadata }, _magic_start_initializers, _magic_start_extraInitializers);
|
61
|
+
__esDecorate(null, null, _segments_decorators, { kind: "field", name: "segments", static: false, private: false, access: { has: obj => "segments" in obj, get: obj => obj.segments, set: (obj, value) => { obj.segments = value; } }, metadata: _metadata }, _segments_initializers, _segments_extraInitializers);
|
62
|
+
__esDecorate(null, null, _magic_end_decorators, { kind: "field", name: "magic_end", static: false, private: false, access: { has: obj => "magic_end" in obj, get: obj => obj.magic_end, set: (obj, value) => { obj.magic_end = value; } }, metadata: _metadata }, _magic_end_initializers, _magic_end_extraInitializers);
|
63
|
+
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
|
64
|
+
Header = _classThis = _classDescriptor.value;
|
65
|
+
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
66
|
+
__runInitializers(_classThis, _classExtraInitializers);
|
67
|
+
}
|
68
|
+
magic_start = __runInitializers(this, _magic_start_initializers, 'test');
|
69
|
+
segments = (__runInitializers(this, _magic_start_extraInitializers), __runInitializers(this, _segments_initializers, 0));
|
70
|
+
magic_end = (__runInitializers(this, _segments_extraInitializers), __runInitializers(this, _magic_end_initializers, 'end'));
|
71
|
+
constructor() {
|
72
|
+
__runInitializers(this, _magic_end_extraInitializers);
|
73
|
+
}
|
74
|
+
};
|
75
|
+
return Header = _classThis;
|
76
|
+
})();
|
77
|
+
let AnotherHeader = (() => {
|
78
|
+
var _a;
|
79
|
+
let _classDecorators = [struct()];
|
80
|
+
let _classDescriptor;
|
81
|
+
let _classExtraInitializers = [];
|
82
|
+
let _classThis;
|
83
|
+
let _classSuper = Header;
|
84
|
+
let __plus_decorators;
|
85
|
+
let __plus_initializers = [];
|
86
|
+
let __plus_extraInitializers = [];
|
87
|
+
var AnotherHeader = class extends _classSuper {
|
88
|
+
static { _classThis = this; }
|
89
|
+
static {
|
90
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
|
91
|
+
__plus_decorators = [(_a = t).uint64.bind(_a)];
|
92
|
+
__esDecorate(null, null, __plus_decorators, { kind: "field", name: "_plus", static: false, private: false, access: { has: obj => "_plus" in obj, get: obj => obj._plus, set: (obj, value) => { obj._plus = value; } }, metadata: _metadata }, __plus_initializers, __plus_extraInitializers);
|
93
|
+
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
|
94
|
+
AnotherHeader = _classThis = _classDescriptor.value;
|
95
|
+
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
96
|
+
__runInitializers(_classThis, _classExtraInitializers);
|
97
|
+
}
|
98
|
+
_plus = __runInitializers(this, __plus_initializers, 0x12345678);
|
99
|
+
constructor() {
|
100
|
+
super(...arguments);
|
101
|
+
__runInitializers(this, __plus_extraInitializers);
|
102
|
+
}
|
103
|
+
};
|
104
|
+
return AnotherHeader = _classThis;
|
105
|
+
})();
|
106
|
+
let Segment = (() => {
|
107
|
+
var _a;
|
108
|
+
let _classDecorators = [struct()];
|
109
|
+
let _classDescriptor;
|
110
|
+
let _classExtraInitializers = [];
|
111
|
+
let _classThis;
|
112
|
+
let _id_decorators;
|
113
|
+
let _id_initializers = [];
|
114
|
+
let _id_extraInitializers = [];
|
115
|
+
let _data_decorators;
|
116
|
+
let _data_initializers = [];
|
117
|
+
let _data_extraInitializers = [];
|
118
|
+
var Segment = class {
|
119
|
+
static { _classThis = this; }
|
120
|
+
static {
|
121
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
|
122
|
+
_id_decorators = [(_a = t).uint64.bind(_a)];
|
123
|
+
_data_decorators = [t.uint32(64)];
|
124
|
+
__esDecorate(null, null, _id_decorators, { kind: "field", name: "id", static: false, private: false, access: { has: obj => "id" in obj, get: obj => obj.id, set: (obj, value) => { obj.id = value; } }, metadata: _metadata }, _id_initializers, _id_extraInitializers);
|
125
|
+
__esDecorate(null, null, _data_decorators, { kind: "field", name: "data", static: false, private: false, access: { has: obj => "data" in obj, get: obj => obj.data, set: (obj, value) => { obj.data = value; } }, metadata: _metadata }, _data_initializers, _data_extraInitializers);
|
126
|
+
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
|
127
|
+
Segment = _classThis = _classDescriptor.value;
|
128
|
+
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
129
|
+
__runInitializers(_classThis, _classExtraInitializers);
|
130
|
+
}
|
131
|
+
id = __runInitializers(this, _id_initializers, 0x021);
|
132
|
+
data = (__runInitializers(this, _id_extraInitializers), __runInitializers(this, _data_initializers, []));
|
133
|
+
constructor() {
|
134
|
+
__runInitializers(this, _data_extraInitializers);
|
135
|
+
}
|
136
|
+
};
|
137
|
+
return Segment = _classThis;
|
138
|
+
})();
|
139
|
+
let BinObject = (() => {
|
140
|
+
let _classDecorators = [struct()];
|
141
|
+
let _classDescriptor;
|
142
|
+
let _classExtraInitializers = [];
|
143
|
+
let _classThis;
|
144
|
+
let _header_decorators;
|
145
|
+
let _header_initializers = [];
|
146
|
+
let _header_extraInitializers = [];
|
147
|
+
let _comment_decorators;
|
148
|
+
let _comment_initializers = [];
|
149
|
+
let _comment_extraInitializers = [];
|
150
|
+
let _segments_decorators;
|
151
|
+
let _segments_initializers = [];
|
152
|
+
let _segments_extraInitializers = [];
|
153
|
+
var BinObject = class {
|
154
|
+
static { _classThis = this; }
|
155
|
+
static {
|
156
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
|
157
|
+
_header_decorators = [member(AnotherHeader)];
|
158
|
+
_comment_decorators = [t.char(32)];
|
159
|
+
_segments_decorators = [member(Segment, 16)];
|
160
|
+
__esDecorate(null, null, _header_decorators, { kind: "field", name: "header", static: false, private: false, access: { has: obj => "header" in obj, get: obj => obj.header, set: (obj, value) => { obj.header = value; } }, metadata: _metadata }, _header_initializers, _header_extraInitializers);
|
161
|
+
__esDecorate(null, null, _comment_decorators, { kind: "field", name: "comment", static: false, private: false, access: { has: obj => "comment" in obj, get: obj => obj.comment, set: (obj, value) => { obj.comment = value; } }, metadata: _metadata }, _comment_initializers, _comment_extraInitializers);
|
162
|
+
__esDecorate(null, null, _segments_decorators, { kind: "field", name: "segments", static: false, private: false, access: { has: obj => "segments" in obj, get: obj => obj.segments, set: (obj, value) => { obj.segments = value; } }, metadata: _metadata }, _segments_initializers, _segments_extraInitializers);
|
163
|
+
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
|
164
|
+
BinObject = _classThis = _classDescriptor.value;
|
165
|
+
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
166
|
+
__runInitializers(_classThis, _classExtraInitializers);
|
167
|
+
}
|
168
|
+
header = __runInitializers(this, _header_initializers, new AnotherHeader());
|
169
|
+
comment = (__runInitializers(this, _header_extraInitializers), __runInitializers(this, _comment_initializers, ''));
|
170
|
+
segments = (__runInitializers(this, _comment_extraInitializers), __runInitializers(this, _segments_initializers, [new Segment()]));
|
171
|
+
constructor() {
|
172
|
+
__runInitializers(this, _segments_extraInitializers);
|
173
|
+
}
|
174
|
+
};
|
175
|
+
return BinObject = _classThis;
|
176
|
+
})();
|
177
|
+
const obj = new BinObject();
|
178
|
+
obj.comment = '!!! Omg, hi! this is cool' + '.'.repeat(32);
|
179
|
+
obj.header.segments = 1;
|
180
|
+
const segment = new Segment();
|
181
|
+
segment.data = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
|
182
|
+
serialize(segment);
|
183
|
+
obj.segments = [segment];
|
184
|
+
const bin = serialize(obj);
|
185
|
+
writeFileSync(join(import.meta.dirname, '../tmp/bin'), bin);
|
186
|
+
const omg = new BinObject();
|
187
|
+
deserialize(omg, bin);
|
188
|
+
console.log(omg);
|
package/package.json
CHANGED
package/src/internal/struct.ts
CHANGED
@@ -7,9 +7,7 @@ export interface MemberInit {
|
|
7
7
|
length?: number;
|
8
8
|
}
|
9
9
|
|
10
|
-
export const init = Symbol('struct_init');
|
11
|
-
|
12
|
-
export type init = typeof init;
|
10
|
+
export const init: unique symbol = Symbol('struct_init');
|
13
11
|
|
14
12
|
/**
|
15
13
|
* Options for struct initialization
|
@@ -31,23 +29,53 @@ export interface Metadata {
|
|
31
29
|
size: number;
|
32
30
|
}
|
33
31
|
|
34
|
-
export const metadata = Symbol('struct');
|
32
|
+
export const metadata: unique symbol = Symbol('struct');
|
35
33
|
|
36
|
-
export
|
34
|
+
export interface _DecoratorMetadata<T extends Metadata = Metadata> extends DecoratorMetadata {
|
35
|
+
[metadata]?: T;
|
36
|
+
[init]?: MemberInit[];
|
37
|
+
}
|
38
|
+
|
39
|
+
export interface DecoratorContext<T extends Metadata = Metadata> {
|
40
|
+
metadata: _DecoratorMetadata<T>;
|
41
|
+
}
|
42
|
+
|
43
|
+
export type MemberContext = ClassMemberDecoratorContext & DecoratorContext;
|
37
44
|
|
38
45
|
export interface Static<T extends Metadata = Metadata> {
|
39
|
-
[metadata]:
|
40
|
-
|
41
|
-
|
46
|
+
[Symbol.metadata]: DecoratorMetadata & {
|
47
|
+
[metadata]: T;
|
48
|
+
};
|
49
|
+
new (): Instance<T>;
|
50
|
+
prototype: Instance<T>;
|
42
51
|
}
|
43
52
|
|
44
53
|
export interface StaticLike<T extends Metadata = Metadata> extends ClassLike {
|
45
|
-
[metadata]?: T;
|
46
|
-
|
54
|
+
[Symbol.metadata]?: _DecoratorMetadata<T> | null;
|
55
|
+
}
|
56
|
+
|
57
|
+
export function isValidMetadata<T extends Metadata = Metadata>(
|
58
|
+
arg: unknown
|
59
|
+
): arg is DecoratorMetadata & {
|
60
|
+
[metadata]: T;
|
61
|
+
} {
|
62
|
+
return arg != null && typeof arg == 'object' && metadata in arg;
|
63
|
+
}
|
64
|
+
|
65
|
+
/**
|
66
|
+
* Gets a reference to Symbol.metadata, even on platforms that do not expose it globally (like Node)
|
67
|
+
*/
|
68
|
+
export function symbol_metadata(arg: ClassLike): typeof Symbol.metadata {
|
69
|
+
const symbol_metadata = Symbol.metadata || Object.getOwnPropertySymbols(arg).find(s => s.description == 'Symbol.metadata');
|
70
|
+
if (!symbol_metadata) {
|
71
|
+
throw new ReferenceError('Could not get a reference to Symbol.metadata');
|
72
|
+
}
|
73
|
+
|
74
|
+
return symbol_metadata as typeof Symbol.metadata;
|
47
75
|
}
|
48
76
|
|
49
77
|
export function isStatic<T extends Metadata = Metadata>(arg: unknown): arg is Static<T> {
|
50
|
-
return typeof arg == 'function' &&
|
78
|
+
return typeof arg == 'function' && symbol_metadata(arg as ClassLike) in arg && isValidMetadata(arg[symbol_metadata(arg as ClassLike)]);
|
51
79
|
}
|
52
80
|
|
53
81
|
export interface Instance<T extends Metadata = Metadata> {
|
@@ -59,7 +87,7 @@ export interface InstanceLike<T extends Metadata = Metadata> {
|
|
59
87
|
}
|
60
88
|
|
61
89
|
export function isInstance<T extends Metadata = Metadata>(arg: unknown): arg is Instance<T> {
|
62
|
-
return
|
90
|
+
return arg != null && typeof arg == 'object' && isStatic(arg.constructor);
|
63
91
|
}
|
64
92
|
|
65
93
|
export function isStruct<T extends Metadata = Metadata>(arg: unknown): arg is Instance<T> | Static<T> {
|
package/src/struct.ts
CHANGED
@@ -1,29 +1,44 @@
|
|
1
|
-
import * as
|
1
|
+
import * as primitive from './internal/primitives.js';
|
2
|
+
import {
|
3
|
+
DecoratorContext,
|
4
|
+
InstanceLike,
|
5
|
+
MemberInit,
|
6
|
+
Metadata,
|
7
|
+
Options,
|
8
|
+
Size,
|
9
|
+
StaticLike,
|
10
|
+
symbol_metadata,
|
11
|
+
init,
|
12
|
+
isInstance,
|
13
|
+
isStatic,
|
14
|
+
isStruct,
|
15
|
+
metadata,
|
16
|
+
type MemberContext,
|
17
|
+
} from './internal/struct.js';
|
2
18
|
import { capitalize } from './string.js';
|
3
19
|
import { ClassLike } from './types.js';
|
4
|
-
|
5
|
-
export { Struct };
|
20
|
+
export * as Struct from './internal/struct.js';
|
6
21
|
|
7
22
|
/**
|
8
23
|
* Gets the size in bytes of a type
|
9
24
|
*/
|
10
|
-
export function sizeof<T extends primitive.Valid |
|
25
|
+
export function sizeof<T extends primitive.Valid | StaticLike | InstanceLike>(type: T): Size<T> {
|
11
26
|
// primitive
|
12
27
|
if (typeof type == 'string') {
|
13
28
|
if (!primitive.isValid(type)) {
|
14
29
|
throw new TypeError('Invalid primitive type: ' + type);
|
15
30
|
}
|
16
31
|
|
17
|
-
return (+primitive.normalize(type).match(primitive.regex)![2] / 8) as
|
32
|
+
return (+primitive.normalize(type).match(primitive.regex)![2] / 8) as Size<T>;
|
18
33
|
}
|
19
34
|
|
20
|
-
if (!
|
35
|
+
if (!isStruct(type)) {
|
21
36
|
throw new TypeError('Not a struct');
|
22
37
|
}
|
23
38
|
|
24
|
-
const
|
39
|
+
const struct = isStatic(type) ? type : type.constructor;
|
25
40
|
|
26
|
-
return
|
41
|
+
return struct[symbol_metadata(struct)][metadata].size as Size<T>;
|
27
42
|
}
|
28
43
|
|
29
44
|
/**
|
@@ -36,14 +51,16 @@ export function align(value: number, alignment: number): number {
|
|
36
51
|
/**
|
37
52
|
* Decorates a class as a struct
|
38
53
|
*/
|
39
|
-
export function struct(options: Partial<
|
54
|
+
export function struct(options: Partial<Options> = {}) {
|
40
55
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
41
|
-
return function (target:
|
42
|
-
|
56
|
+
return function __decorateStruct<const T extends StaticLike>(target: T, context: ClassDecoratorContext & DecoratorContext): T {
|
57
|
+
context.metadata ??= {};
|
58
|
+
context.metadata[init] ||= [];
|
43
59
|
let size = 0;
|
44
60
|
const members = new Map();
|
45
|
-
for (const
|
46
|
-
|
61
|
+
for (const _ of context.metadata[init]) {
|
62
|
+
const { name, type, length } = _;
|
63
|
+
if (!primitive.isValid(type) && !isStatic(type)) {
|
47
64
|
throw new TypeError('Not a valid type: ' + type);
|
48
65
|
}
|
49
66
|
members.set(name, {
|
@@ -55,7 +72,8 @@ export function struct(options: Partial<Struct.Options> = {}) {
|
|
55
72
|
size = align(size, options.align || 1);
|
56
73
|
}
|
57
74
|
|
58
|
-
|
75
|
+
context.metadata[metadata] = { options, members, size } satisfies Metadata;
|
76
|
+
return target;
|
59
77
|
};
|
60
78
|
}
|
61
79
|
|
@@ -63,8 +81,8 @@ export function struct(options: Partial<Struct.Options> = {}) {
|
|
63
81
|
* Decorates a class member to be serialized
|
64
82
|
*/
|
65
83
|
export function member(type: primitive.Valid | ClassLike, length?: number) {
|
66
|
-
return function (
|
67
|
-
let name =
|
84
|
+
return function <V>(value: V, context: MemberContext): V {
|
85
|
+
let name = context.name;
|
68
86
|
if (typeof name == 'symbol') {
|
69
87
|
console.warn('Symbol used for struct member name will be coerced to string: ' + name.toString());
|
70
88
|
name = name.toString();
|
@@ -74,18 +92,10 @@ export function member(type: primitive.Valid | ClassLike, length?: number) {
|
|
74
92
|
throw new ReferenceError('Invalid name for struct member');
|
75
93
|
}
|
76
94
|
|
77
|
-
|
78
|
-
|
79
|
-
}
|
80
|
-
|
81
|
-
if (!('constructor' in target)) {
|
82
|
-
throw new TypeError('Invalid member for struct field');
|
83
|
-
}
|
84
|
-
|
85
|
-
const struct = (target as Struct.InstanceLike).constructor;
|
86
|
-
|
87
|
-
struct[Struct.init] ||= [];
|
88
|
-
struct[Struct.init].push({ name, type, length } satisfies Struct.MemberInit);
|
95
|
+
context.metadata ??= {};
|
96
|
+
context.metadata[init] ||= [];
|
97
|
+
context.metadata[init].push({ name, type, length } satisfies MemberInit);
|
98
|
+
return value;
|
89
99
|
};
|
90
100
|
}
|
91
101
|
|
@@ -93,10 +103,10 @@ export function member(type: primitive.Valid | ClassLike, length?: number) {
|
|
93
103
|
* Serializes a struct into a Uint8Array
|
94
104
|
*/
|
95
105
|
export function serialize(instance: unknown): Uint8Array {
|
96
|
-
if (!
|
106
|
+
if (!isInstance(instance)) {
|
97
107
|
throw new TypeError('Can not serialize, not a struct instance');
|
98
108
|
}
|
99
|
-
const { options, members } = instance.constructor[
|
109
|
+
const { options, members } = instance.constructor[symbol_metadata(instance.constructor)][metadata];
|
100
110
|
|
101
111
|
const buffer = new Uint8Array(sizeof(instance));
|
102
112
|
const view = new DataView(buffer.buffer);
|
@@ -139,10 +149,10 @@ export function serialize(instance: unknown): Uint8Array {
|
|
139
149
|
* Deserializes a struct from a Uint8Array
|
140
150
|
*/
|
141
151
|
export function deserialize(instance: unknown, _buffer: ArrayBuffer | ArrayBufferView) {
|
142
|
-
if (!
|
152
|
+
if (!isInstance(instance)) {
|
143
153
|
throw new TypeError('Can not deserialize, not a struct instance');
|
144
154
|
}
|
145
|
-
const { options, members } = instance.constructor[
|
155
|
+
const { options, members } = instance.constructor[symbol_metadata(instance.constructor)][metadata];
|
146
156
|
|
147
157
|
const buffer = new Uint8Array('buffer' in _buffer ? _buffer.buffer : _buffer);
|
148
158
|
|
@@ -191,22 +201,17 @@ export function deserialize(instance: unknown, _buffer: ArrayBuffer | ArrayBuffe
|
|
191
201
|
}
|
192
202
|
}
|
193
203
|
|
194
|
-
/**
|
195
|
-
* Also can be a name when legacy decorators are used
|
196
|
-
*/
|
197
|
-
type Context = string | symbol | ClassMemberDecoratorContext;
|
198
|
-
|
199
204
|
function _member<T extends primitive.Valid>(type: T) {
|
200
|
-
function
|
201
|
-
function
|
202
|
-
function
|
203
|
-
if (typeof
|
204
|
-
return member(type,
|
205
|
+
function _structMemberDecorator<const V>(length: number): (value: V, context: MemberContext) => V;
|
206
|
+
function _structMemberDecorator<const V>(value: V, context: MemberContext): V;
|
207
|
+
function _structMemberDecorator<const V>(valueOrLength: V | number, context?: MemberContext): V | ((value: V, context: MemberContext) => V) {
|
208
|
+
if (typeof valueOrLength == 'number') {
|
209
|
+
return member(type, valueOrLength);
|
205
210
|
}
|
206
211
|
|
207
|
-
return member(type)(
|
212
|
+
return member(type)(valueOrLength, context!);
|
208
213
|
}
|
209
|
-
return
|
214
|
+
return _structMemberDecorator;
|
210
215
|
}
|
211
216
|
|
212
217
|
/**
|
package/tsconfig.json
CHANGED
@@ -10,13 +10,12 @@
|
|
10
10
|
"esModuleInterop": true,
|
11
11
|
"noImplicitThis": true,
|
12
12
|
"declaration": true,
|
13
|
-
"experimentalDecorators": true,
|
14
13
|
"strict": true
|
15
14
|
},
|
16
15
|
"typedocOptions": {
|
17
16
|
"entryPoints": ["src/index.ts"],
|
18
17
|
"out": "docs"
|
19
18
|
},
|
20
|
-
"include": ["./src/**/*.ts"],
|
19
|
+
"include": ["./src/**/*.ts", "./test/**/*.ts"],
|
21
20
|
"exclude": ["node_modules"]
|
22
21
|
}
|
package/dist/internal/struct.js
DELETED
@@ -1,11 +0,0 @@
|
|
1
|
-
export const init = Symbol('struct_init');
|
2
|
-
export const metadata = Symbol('struct');
|
3
|
-
export function isStatic(arg) {
|
4
|
-
return typeof arg == 'function' && metadata in arg;
|
5
|
-
}
|
6
|
-
export function isInstance(arg) {
|
7
|
-
return metadata in (arg?.constructor || {});
|
8
|
-
}
|
9
|
-
export function isStruct(arg) {
|
10
|
-
return isInstance(arg) || isStatic(arg);
|
11
|
-
}
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|