utilium 1.10.0 → 2.0.0-pre.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.
@@ -1,57 +1,39 @@
1
1
  import type { ClassLike } from '../types.js';
2
2
  import type * as primitive from './primitives.js';
3
3
 
4
- declare global {
5
- interface SymbolConstructor {
6
- readonly size: unique symbol;
7
- readonly serialize: unique symbol;
8
- readonly deserialize: unique symbol;
9
- }
10
- }
11
-
12
4
  /**
13
5
  * Polyfill Symbol.metadata
14
6
  * @see https://github.com/microsoft/TypeScript/issues/53461
15
7
  */
16
8
  (Symbol as { metadata: symbol }).metadata ??= Symbol.for('Symbol.metadata');
17
9
 
18
- Object.assign(Symbol, {
19
- size: Symbol('uSize'),
20
- serialize: Symbol('uSerialize'),
21
- deserialize: Symbol('uDeserialize'),
22
- });
10
+ export type TypeLike = primitive.Type | Like | primitive.Valid | undefined | null;
23
11
 
24
- export type TypeLike = Custom | Like | primitive.Valid | undefined | null;
25
-
26
- export type Type = Custom | Static | primitive.Typename;
27
-
28
- /**
29
- * Member initialization data
30
- * This is needed since class decorators are called *after* member decorators
31
- */
32
- export interface MemberInit {
33
- name: string;
34
- type: string | ClassLike;
35
- length?: number | string;
36
- }
12
+ export type Type = Static | primitive.Type;
37
13
 
38
14
  /**
39
15
  * Options for struct initialization
40
16
  */
41
17
  export interface Options {
18
+ packed: boolean;
42
19
  align: number;
43
- bigEndian: boolean;
44
20
  isUnion: boolean;
45
21
  }
46
22
 
47
23
  export interface Member {
48
24
  name: string;
49
25
  type: Type;
50
- staticOffset: number;
26
+ offset: number;
27
+
28
+ /** The size of the member, 0 for dynamically sized arrays */
29
+ size: number;
51
30
  length?: number | string;
52
31
 
53
32
  /** A C-style type/name declaration string, used for diagnostics */
54
33
  decl: string;
34
+
35
+ /** Whether the member is little endian */
36
+ littleEndian: boolean;
55
37
  }
56
38
 
57
39
  export interface Metadata {
@@ -66,9 +48,16 @@ export interface Metadata {
66
48
  isUnion: boolean;
67
49
  }
68
50
 
51
+ export interface Init {
52
+ members: Member[];
53
+ size: number;
54
+ isDynamic: boolean;
55
+ isUnion: boolean;
56
+ }
57
+
69
58
  type _DecoratorMetadata<T extends Metadata = Metadata> = DecoratorMetadata & {
70
59
  struct?: T;
71
- structInit?: MemberInit[];
60
+ structInit?: Init;
72
61
  };
73
62
 
74
63
  export interface DecoratorContext<T extends Metadata = Metadata> {
@@ -79,25 +68,34 @@ export interface DecoratorContext<T extends Metadata = Metadata> {
79
68
  * Initializes the struct metadata for a class
80
69
  * This also handles copying metadata from parent classes
81
70
  */
82
- export function initMetadata(context: DecoratorContext): MemberInit[] {
71
+ export function initMetadata(context: DecoratorContext): Init {
83
72
  context.metadata ??= {};
84
73
 
85
- context.metadata.structInit = [...(context.metadata.structInit ?? [])];
74
+ const existing: Partial<Init> = context.metadata.structInit ?? {};
75
+
76
+ context.metadata.structInit = {
77
+ members: [...(existing.members ?? [])],
78
+ size: existing.size ?? 0,
79
+ isDynamic: existing.isDynamic ?? false,
80
+ isUnion: existing.isUnion ?? false,
81
+ };
86
82
 
87
83
  return context.metadata.structInit;
88
84
  }
89
85
 
90
- export type MemberContext = ClassMemberDecoratorContext & DecoratorContext;
91
-
92
86
  export interface Static<T extends Metadata = Metadata> {
93
- [Symbol.metadata]: { struct: T };
94
- new (): Instance<T>;
95
- prototype: Instance<T>;
87
+ [Symbol.metadata]: Required<_DecoratorMetadata<T>>;
88
+ readonly prototype: Instance<T>;
89
+ new <TArrayBuffer extends ArrayBufferLike = ArrayBuffer>(
90
+ buffer: TArrayBuffer,
91
+ byteOffset?: number,
92
+ length?: number
93
+ ): Instance<T> & ArrayBufferView<TArrayBuffer>;
94
+ new (array?: ArrayLike<number> | ArrayBuffer): Instance<T>;
96
95
  }
97
96
 
98
97
  export interface StaticLike<T extends Metadata = Metadata> extends ClassLike {
99
98
  [Symbol.metadata]?: _DecoratorMetadata<T> | null;
100
- new (): unknown;
101
99
  }
102
100
 
103
101
  export function isValidMetadata<T extends Metadata = Metadata>(
@@ -108,27 +106,11 @@ export function isValidMetadata<T extends Metadata = Metadata>(
108
106
  return arg != null && typeof arg == 'object' && 'struct' in arg;
109
107
  }
110
108
 
111
- /**
112
- * Polyfill context.metadata
113
- * @see https://github.com/microsoft/TypeScript/issues/53461
114
- * @internal @hidden
115
- */
116
- export function _polyfill_metadata(target: object): void {
117
- if (Symbol.metadata in target) return;
118
-
119
- Object.defineProperty(target, Symbol.metadata, {
120
- enumerable: true,
121
- configurable: true,
122
- writable: true,
123
- value: Object.create(null),
124
- });
125
- }
126
-
127
109
  export function isStatic<T extends Metadata = Metadata>(arg: unknown): arg is Static<T> {
128
110
  return typeof arg == 'function' && Symbol.metadata in arg && isValidMetadata(arg[Symbol.metadata]);
129
111
  }
130
112
 
131
- export interface Instance<T extends Metadata = Metadata> {
113
+ export interface Instance<T extends Metadata = Metadata> extends ArrayBufferView, Record<PropertyKey, any> {
132
114
  constructor: Static<T>;
133
115
  }
134
116
 
@@ -162,25 +144,10 @@ export function checkStruct<T extends Metadata = Metadata>(arg: unknown): assert
162
144
  );
163
145
  }
164
146
 
165
- /**
166
- * A "custom" type, which can be used to implement non-builtin size, serialization, and deserialization
167
- */
168
- export interface Custom {
169
- readonly [Symbol.size]: number;
170
- [Symbol.serialize]?(): Uint8Array;
171
- [Symbol.deserialize]?(value: Uint8Array): void;
172
- }
173
-
174
- export function isCustom(arg: unknown): arg is Custom {
175
- return typeof arg == 'object' && arg != null && Symbol.size in arg;
176
- }
177
-
178
147
  export type Like<T extends Metadata = Metadata> = InstanceLike<T> | StaticLike<T>;
179
148
 
180
149
  export type Size<T extends TypeLike> = T extends undefined | null
181
150
  ? 0
182
- : T extends { readonly [Symbol.size]: infer S extends number }
183
- ? S
184
- : T extends primitive.Valid
185
- ? primitive.Size<T>
186
- : number;
151
+ : T extends primitive.Valid
152
+ ? primitive.Size<T>
153
+ : number;
package/src/objects.ts CHANGED
@@ -136,3 +136,10 @@ export function bindFunctions<T extends object, This = any>(fns: T, thisValue: T
136
136
  Object.entries(fns).map(([k, v]) => [k, typeof v == 'function' ? v.bind(thisValue) : v])
137
137
  ) as Bound<T, This>;
138
138
  }
139
+
140
+ /**
141
+ * Makes all properties in T mutable
142
+ */
143
+ export type Mutable<T> = {
144
+ -readonly [P in keyof T]: T[P];
145
+ };
package/src/string.ts CHANGED
@@ -36,7 +36,13 @@ const decoder = new TextDecoder();
36
36
  * Decodes a UTF-8 string from a buffer
37
37
  */
38
38
  export function decodeUTF8(input?: Uint8Array): string {
39
- return decoder.decode(input);
39
+ if (!input) return '';
40
+
41
+ if (input.buffer instanceof ArrayBuffer && !input.buffer.resizable) return decoder.decode(input);
42
+
43
+ const buffer = new Uint8Array(input.byteLength);
44
+ buffer.set(input);
45
+ return decoder.decode(buffer);
40
46
  }
41
47
 
42
48
  export function encodeASCII(input: string): Uint8Array {