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.
Files changed (31) hide show
  1. package/dist/{internal → src/internal}/struct.d.ts +21 -7
  2. package/dist/src/internal/struct.js +24 -0
  3. package/dist/{struct.d.ts → src/struct.d.ts} +8 -12
  4. package/dist/{struct.js → src/struct.js} +29 -31
  5. package/dist/test/struct-test.d.ts +1 -0
  6. package/dist/test/struct-test.js +188 -0
  7. package/package.json +1 -1
  8. package/src/internal/struct.ts +40 -12
  9. package/src/struct.ts +49 -44
  10. package/tsconfig.json +1 -2
  11. package/dist/internal/struct.js +0 -11
  12. /package/dist/{fs.d.ts → src/fs.d.ts} +0 -0
  13. /package/dist/{fs.js → src/fs.js} +0 -0
  14. /package/dist/{index.d.ts → src/index.d.ts} +0 -0
  15. /package/dist/{index.js → src/index.js} +0 -0
  16. /package/dist/{internal → src/internal}/primitives.d.ts +0 -0
  17. /package/dist/{internal → src/internal}/primitives.js +0 -0
  18. /package/dist/{list.d.ts → src/list.d.ts} +0 -0
  19. /package/dist/{list.js → src/list.js} +0 -0
  20. /package/dist/{misc.d.ts → src/misc.d.ts} +0 -0
  21. /package/dist/{misc.js → src/misc.js} +0 -0
  22. /package/dist/{numbers.d.ts → src/numbers.d.ts} +0 -0
  23. /package/dist/{numbers.js → src/numbers.js} +0 -0
  24. /package/dist/{objects.d.ts → src/objects.d.ts} +0 -0
  25. /package/dist/{objects.js → src/objects.js} +0 -0
  26. /package/dist/{random.d.ts → src/random.d.ts} +0 -0
  27. /package/dist/{random.js → src/random.js} +0 -0
  28. /package/dist/{string.d.ts → src/string.d.ts} +0 -0
  29. /package/dist/{string.js → src/string.js} +0 -0
  30. /package/dist/{types.d.ts → src/types.d.ts} +0 -0
  31. /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 type metadata = typeof metadata;
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]: T;
31
- new (): Instance;
32
- prototype: Instance;
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
- export { Struct };
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 | Struct.StaticLike | Struct.InstanceLike>(type: T): Struct.Size<T>;
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<Struct.Options>): (target: Struct.StaticLike, _?: ClassDecoratorContext) => void;
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): (target: object, context?: ClassMemberDecoratorContext | string | symbol) => void;
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): (target: object, context?: Context) => void;
35
- (target: object, context?: Context): void;
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
- export { Struct };
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 (!Struct.isStruct(type)) {
16
+ if (!isStruct(type)) {
17
17
  throw new TypeError('Not a struct');
18
18
  }
19
- const meta = Struct.isStatic(type) ? type[Struct.metadata] : type.constructor[Struct.metadata];
20
- return meta.size;
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
- target[Struct.init] ||= [];
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 { name, type, length } of target[Struct.init]) {
38
- if (!primitive.isValid(type) && !Struct.isStatic(type)) {
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
- target[Struct.metadata] = { options, members, size };
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 (target, context) {
57
- let name = typeof context == 'object' ? context.name : context;
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
- if (typeof target != 'object') {
66
- throw new TypeError('Invalid member for struct field');
67
- }
68
- if (!('constructor' in target)) {
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 (!Struct.isInstance(instance)) {
78
+ if (!isInstance(instance)) {
81
79
  throw new TypeError('Can not serialize, not a struct instance');
82
80
  }
83
- const { options, members } = instance.constructor[Struct.metadata];
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 (!Struct.isInstance(instance)) {
115
+ if (!isInstance(instance)) {
118
116
  throw new TypeError('Can not deserialize, not a struct instance');
119
117
  }
120
- const { options, members } = instance.constructor[Struct.metadata];
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 _(targetOrLength, context) {
160
- if (typeof targetOrLength == 'number') {
161
- return member(type, targetOrLength);
157
+ function _structMemberDecorator(valueOrLength, context) {
158
+ if (typeof valueOrLength == 'number') {
159
+ return member(type, valueOrLength);
162
160
  }
163
- return member(type)(targetOrLength, context);
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "utilium",
3
- "version": "0.5.10",
3
+ "version": "0.6.1",
4
4
  "description": "Typescript utilies",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -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 type metadata = typeof metadata;
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]: T;
40
- new (): Instance;
41
- prototype: Instance;
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
- [init]?: MemberInit[];
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' && metadata in arg;
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 metadata in (arg?.constructor || {});
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 Struct from './internal/struct.js';
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
- import * as primitive from './internal/primitives.js';
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 | Struct.StaticLike | Struct.InstanceLike>(type: T): Struct.Size<T> {
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 Struct.Size<T>;
32
+ return (+primitive.normalize(type).match(primitive.regex)![2] / 8) as Size<T>;
18
33
  }
19
34
 
20
- if (!Struct.isStruct(type)) {
35
+ if (!isStruct(type)) {
21
36
  throw new TypeError('Not a struct');
22
37
  }
23
38
 
24
- const meta: Struct.Metadata = Struct.isStatic(type) ? type[Struct.metadata] : type.constructor[Struct.metadata];
39
+ const struct = isStatic(type) ? type : type.constructor;
25
40
 
26
- return meta.size as Struct.Size<T>;
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<Struct.Options> = {}) {
54
+ export function struct(options: Partial<Options> = {}) {
40
55
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
41
- return function (target: Struct.StaticLike, _?: ClassDecoratorContext) {
42
- target[Struct.init] ||= [];
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 { name, type, length } of target[Struct.init]) {
46
- if (!primitive.isValid(type) && !Struct.isStatic(type)) {
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
- target[Struct.metadata] = { options, members, size } satisfies Struct.Metadata;
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 (target: object, context?: ClassMemberDecoratorContext | string | symbol) {
67
- let name = typeof context == 'object' ? context.name : context;
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
- if (typeof target != 'object') {
78
- throw new TypeError('Invalid member for struct field');
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 (!Struct.isInstance(instance)) {
106
+ if (!isInstance(instance)) {
97
107
  throw new TypeError('Can not serialize, not a struct instance');
98
108
  }
99
- const { options, members } = instance.constructor[Struct.metadata];
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 (!Struct.isInstance(instance)) {
152
+ if (!isInstance(instance)) {
143
153
  throw new TypeError('Can not deserialize, not a struct instance');
144
154
  }
145
- const { options, members } = instance.constructor[Struct.metadata];
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 _(length: number): (target: object, context?: Context) => void;
201
- function _(target: object, context?: Context): void;
202
- function _(targetOrLength: object | number, context?: Context) {
203
- if (typeof targetOrLength == 'number') {
204
- return member(type, targetOrLength);
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)(targetOrLength, context);
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
  }
@@ -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