utilium 1.2.9 → 1.3.0

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/cache.d.ts CHANGED
@@ -37,20 +37,16 @@ export interface Region {
37
37
  export declare class Resource<ID> {
38
38
  /** The resource ID */
39
39
  readonly id: ID;
40
- /** The full size of the resource */
41
- size: number;
40
+ protected _size: number;
42
41
  protected readonly options: Options;
43
42
  /** Regions used to reduce unneeded allocations. Think of sparse arrays. */
44
43
  readonly regions: Region[];
44
+ /** The full size of the resource */
45
+ get size(): number;
46
+ set size(value: number);
45
47
  constructor(
46
48
  /** The resource ID */
47
- id: ID,
48
- /** The full size of the resource */
49
- size: number, options: Options, resources?: Map<ID, Resource<ID> | undefined>);
50
- /**
51
- * Ensure the full size of the resource is *at least* `newSize`
52
- */
53
- grow(newSize: number): void;
49
+ id: ID, _size: number, options: Options, resources?: Map<ID, Resource<ID> | undefined>);
54
50
  /** Combines adjacent regions and combines adjacent ranges within a region */
55
51
  collect(): void;
56
52
  /** Takes an initial range and finds the sub-ranges that are not in the cache */
package/dist/cache.js CHANGED
@@ -6,29 +6,51 @@ import { extendBuffer } from './buffer.js';
6
6
  */
7
7
  export class Resource {
8
8
  id;
9
- size;
9
+ _size;
10
10
  options;
11
11
  /** Regions used to reduce unneeded allocations. Think of sparse arrays. */
12
12
  regions = [];
13
+ /** The full size of the resource */
14
+ get size() {
15
+ return this._size;
16
+ }
17
+ set size(value) {
18
+ if (value >= this._size) {
19
+ this._size = value;
20
+ return;
21
+ }
22
+ this._size = value;
23
+ for (let i = this.regions.length - 1; i >= 0; i--) {
24
+ const region = this.regions[i];
25
+ if (region.offset >= value) {
26
+ this.regions.splice(i, 1);
27
+ continue;
28
+ }
29
+ const maxLength = value - region.offset;
30
+ if (region.data.byteLength > maxLength) {
31
+ region.data = region.data.subarray(0, maxLength);
32
+ }
33
+ region.ranges = region.ranges
34
+ .filter(range => range.start < value)
35
+ .map(range => {
36
+ if (range.end > value) {
37
+ return { start: range.start, end: value };
38
+ }
39
+ return range;
40
+ });
41
+ }
42
+ }
13
43
  constructor(
14
44
  /** The resource ID */
15
- id,
16
- /** The full size of the resource */
17
- size, options, resources) {
45
+ id, _size, options, resources) {
18
46
  this.id = id;
19
- this.size = size;
47
+ this._size = _size;
20
48
  this.options = options;
21
49
  options.sparse ??= true;
22
50
  if (!options.sparse)
23
- this.regions.push({ offset: 0, data: new Uint8Array(size), ranges: [] });
51
+ this.regions.push({ offset: 0, data: new Uint8Array(_size), ranges: [] });
24
52
  resources?.set(id, this);
25
53
  }
26
- /**
27
- * Ensure the full size of the resource is *at least* `newSize`
28
- */
29
- grow(newSize) {
30
- this.size = Math.max(this.size, newSize);
31
- }
32
54
  /** Combines adjacent regions and combines adjacent ranges within a region */
33
55
  collect() {
34
56
  if (!this.options.sparse)
@@ -143,6 +165,7 @@ export class Resource {
143
165
  region.data.set(data, offset);
144
166
  region.ranges.push({ start: offset, end });
145
167
  region.ranges.sort((a, b) => a.start - b.start);
168
+ this.collect();
146
169
  return this;
147
170
  }
148
171
  // Find the correct index to insert the new region
@@ -155,6 +178,7 @@ export class Resource {
155
178
  else {
156
179
  this.regions.splice(insertIndex, 0, newRegion); // Insert before the first region with a greater offset
157
180
  }
181
+ this.collect();
158
182
  return this;
159
183
  }
160
184
  }
@@ -3,12 +3,13 @@ type BitsToBytes = {
3
3
  '16': 2;
4
4
  '32': 4;
5
5
  '64': 8;
6
+ '128': 16;
6
7
  };
7
8
  export type Size<T extends string> = T extends `${'int' | 'uint' | 'float'}${infer bits}` ? (bits extends keyof BitsToBytes ? BitsToBytes[bits] : never) : never;
8
- export type Type = `${'int' | 'uint'}${8 | 16 | 32 | 64}` | `float${32 | 64}`;
9
+ export declare const types: readonly ["int8", "uint8", "int16", "uint16", "int32", "uint32", "int64", "uint64", "int128", "uint128", "float32", "float64", "float128"];
10
+ export type Type = (typeof types)[number];
9
11
  export type Valid = Type | Capitalize<Type> | 'char';
10
- export declare const types: ("int8" | "int16" | "int32" | "int64" | "uint8" | "uint16" | "uint32" | "uint64" | "float32" | "float64")[];
11
- export declare const valids: ("int8" | "int16" | "int32" | "int64" | "uint8" | "uint16" | "uint32" | "uint64" | "float32" | "float64" | "Int8" | "Int16" | "Int32" | "Int64" | "Uint8" | "Uint16" | "Uint32" | "Uint64" | "Float32" | "Float64" | "char")[];
12
+ export declare const valids: ("int8" | "uint8" | "int16" | "uint16" | "int32" | "uint32" | "int64" | "uint64" | "int128" | "uint128" | "float32" | "float64" | "float128" | "Int8" | "Uint8" | "Int16" | "Uint16" | "Int32" | "Uint32" | "Int64" | "Uint64" | "Int128" | "Uint128" | "Float32" | "Float64" | "Float128" | "char")[];
12
13
  export declare const regex: RegExp;
13
14
  export type Normalize<T extends Valid> = T extends 'char' ? 'uint8' : Uncapitalize<T>;
14
15
  export declare function normalize<T extends Valid>(type: T): Normalize<T>;
@@ -21,4 +22,5 @@ export declare function isValid(type: {
21
22
  export declare function checkValid(type: {
22
23
  toString(): string;
23
24
  }): asserts type is Valid;
25
+ export declare const mask64: bigint;
24
26
  export {};
@@ -1,7 +1,7 @@
1
1
  import { capitalize } from '../string.js';
2
- export const types = ['int8', 'uint8', 'int16', 'uint16', 'int32', 'uint32', 'int64', 'uint64', 'float32', 'float64'];
2
+ export const types = ['int8', 'uint8', 'int16', 'uint16', 'int32', 'uint32', 'int64', 'uint64', 'int128', 'uint128', 'float32', 'float64', 'float128'];
3
3
  export const valids = [...types, ...types.map(t => capitalize(t)), 'char'];
4
- export const regex = /^(u?int|float)(8|16|32|64)$/i;
4
+ export const regex = /^(u?int|float)(8|16|32|64|128)$/i;
5
5
  export function normalize(type) {
6
6
  return (type == 'char' ? 'uint8' : type.toLowerCase());
7
7
  }
@@ -16,3 +16,4 @@ export function checkValid(type) {
16
16
  throw new TypeError('Not a valid primitive type: ' + type);
17
17
  }
18
18
  }
19
+ export const mask64 = BigInt('0xffffffffffffffff');
package/dist/requests.js CHANGED
@@ -116,7 +116,7 @@ export async function set(url, data, options, init = {}) {
116
116
  const { offset = 0 } = options;
117
117
  if (!options.cacheOnly)
118
118
  await _fetch(new Request(url, init), { method: 'POST' }, true);
119
- resource.add(data, offset).collect();
119
+ resource.add(data, offset);
120
120
  }
121
121
  /**
122
122
  * Make a DELETE request to remove the resource from the server and clear it from the cache.
package/dist/struct.js CHANGED
@@ -88,8 +88,7 @@ export function serialize(instance) {
88
88
  buffer.set(value ? serialize(value) : new Uint8Array(sizeof(type)), iOff);
89
89
  continue;
90
90
  }
91
- const Type = capitalize(type);
92
- const fn = ('set' + Type);
91
+ const fn = `set${capitalize(type)}`;
93
92
  if (fn == 'setInt64') {
94
93
  view.setBigInt64(iOff, BigInt(value), !options.bigEndian);
95
94
  continue;
@@ -98,6 +97,21 @@ export function serialize(instance) {
98
97
  view.setBigUint64(iOff, BigInt(value), !options.bigEndian);
99
98
  continue;
100
99
  }
100
+ if (fn == 'setInt128') {
101
+ view.setBigUint64(iOff + (!options.bigEndian ? 0 : 8), value & primitive.mask64, !options.bigEndian);
102
+ view.setBigInt64(iOff + (!options.bigEndian ? 8 : 0), value >> BigInt(64), !options.bigEndian);
103
+ continue;
104
+ }
105
+ if (fn == 'setUint128') {
106
+ view.setBigUint64(iOff + (!options.bigEndian ? 0 : 8), value & primitive.mask64, !options.bigEndian);
107
+ view.setBigUint64(iOff + (!options.bigEndian ? 8 : 0), value >> BigInt(64), !options.bigEndian);
108
+ continue;
109
+ }
110
+ if (fn == 'setFloat128') {
111
+ view.setFloat64(iOff + (!options.bigEndian ? 0 : 8), Number(value), !options.bigEndian);
112
+ view.setBigUint64(iOff + (!options.bigEndian ? 8 : 0), BigInt(0), !options.bigEndian);
113
+ continue;
114
+ }
101
115
  view[fn](iOff, Number(value), !options.bigEndian);
102
116
  }
103
117
  }
@@ -132,8 +146,7 @@ export function deserialize(instance, _buffer) {
132
146
  if (length > 0) {
133
147
  object ||= [];
134
148
  }
135
- const Type = capitalize(type);
136
- const fn = ('get' + Type);
149
+ const fn = `get${capitalize(type)}`;
137
150
  if (fn == 'getInt64') {
138
151
  object[key] = view.getBigInt64(iOff, !options.bigEndian);
139
152
  continue;
@@ -142,6 +155,22 @@ export function deserialize(instance, _buffer) {
142
155
  object[key] = view.getBigUint64(iOff, !options.bigEndian);
143
156
  continue;
144
157
  }
158
+ if (fn == 'getInt128') {
159
+ object[key] =
160
+ (view.getBigInt64(iOff + (!options.bigEndian ? 8 : 0), !options.bigEndian) << BigInt(64)) |
161
+ view.getBigUint64(iOff + (!options.bigEndian ? 0 : 8), !options.bigEndian);
162
+ continue;
163
+ }
164
+ if (fn == 'getUint128') {
165
+ object[key] =
166
+ (view.getBigUint64(iOff + (!options.bigEndian ? 8 : 0), !options.bigEndian) << BigInt(64)) |
167
+ view.getBigUint64(iOff + (!options.bigEndian ? 0 : 8), !options.bigEndian);
168
+ continue;
169
+ }
170
+ if (fn == 'getFloat128') {
171
+ object[key] = view.getFloat64(iOff + (!options.bigEndian ? 0 : 8), !options.bigEndian);
172
+ continue;
173
+ }
145
174
  object[key] = view[fn](iOff, !options.bigEndian);
146
175
  }
147
176
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "utilium",
3
- "version": "1.2.9",
3
+ "version": "1.3.0",
4
4
  "description": "Typescript utilities",
5
5
  "funding": {
6
6
  "type": "individual",
package/src/cache.ts CHANGED
@@ -45,27 +45,56 @@ export class Resource<ID> {
45
45
  /** Regions used to reduce unneeded allocations. Think of sparse arrays. */
46
46
  public readonly regions: Region[] = [];
47
47
 
48
+ /** The full size of the resource */
49
+ public get size() {
50
+ return this._size;
51
+ }
52
+
53
+ public set size(value: number) {
54
+ if (value >= this._size) {
55
+ this._size = value;
56
+ return;
57
+ }
58
+
59
+ this._size = value;
60
+
61
+ for (let i = this.regions.length - 1; i >= 0; i--) {
62
+ const region = this.regions[i];
63
+
64
+ if (region.offset >= value) {
65
+ this.regions.splice(i, 1);
66
+ continue;
67
+ }
68
+
69
+ const maxLength = value - region.offset;
70
+ if (region.data.byteLength > maxLength) {
71
+ region.data = region.data.subarray(0, maxLength);
72
+ }
73
+
74
+ region.ranges = region.ranges
75
+ .filter(range => range.start < value)
76
+ .map(range => {
77
+ if (range.end > value) {
78
+ return { start: range.start, end: value };
79
+ }
80
+ return range;
81
+ });
82
+ }
83
+ }
84
+
48
85
  public constructor(
49
86
  /** The resource ID */
50
87
  public readonly id: ID,
51
- /** The full size of the resource */
52
- public size: number,
88
+ protected _size: number,
53
89
  protected readonly options: Options,
54
90
  resources?: Map<ID, Resource<ID> | undefined>
55
91
  ) {
56
92
  options.sparse ??= true;
57
- if (!options.sparse) this.regions.push({ offset: 0, data: new Uint8Array(size), ranges: [] });
93
+ if (!options.sparse) this.regions.push({ offset: 0, data: new Uint8Array(_size), ranges: [] });
58
94
 
59
95
  resources?.set(id, this);
60
96
  }
61
97
 
62
- /**
63
- * Ensure the full size of the resource is *at least* `newSize`
64
- */
65
- public grow(newSize: number) {
66
- this.size = Math.max(this.size, newSize);
67
- }
68
-
69
98
  /** Combines adjacent regions and combines adjacent ranges within a region */
70
99
  public collect(): void {
71
100
  if (!this.options.sparse) return;
@@ -191,6 +220,7 @@ export class Resource<ID> {
191
220
  region.ranges.push({ start: offset, end });
192
221
  region.ranges.sort((a, b) => a.start - b.start);
193
222
 
223
+ this.collect();
194
224
  return this;
195
225
  }
196
226
 
@@ -205,6 +235,7 @@ export class Resource<ID> {
205
235
  this.regions.splice(insertIndex, 0, newRegion); // Insert before the first region with a greater offset
206
236
  }
207
237
 
238
+ this.collect();
208
239
  return this;
209
240
  }
210
241
  }
@@ -5,17 +5,20 @@ type BitsToBytes = {
5
5
  '16': 2;
6
6
  '32': 4;
7
7
  '64': 8;
8
+ '128': 16;
8
9
  };
9
10
 
10
11
  export type Size<T extends string> = T extends `${'int' | 'uint' | 'float'}${infer bits}` ? (bits extends keyof BitsToBytes ? BitsToBytes[bits] : never) : never;
11
- export type Type = `${'int' | 'uint'}${8 | 16 | 32 | 64}` | `float${32 | 64}`;
12
- export type Valid = Type | Capitalize<Type> | 'char';
13
12
 
14
- export const types = ['int8', 'uint8', 'int16', 'uint16', 'int32', 'uint32', 'int64', 'uint64', 'float32', 'float64'] satisfies Type[];
13
+ export const types = ['int8', 'uint8', 'int16', 'uint16', 'int32', 'uint32', 'int64', 'uint64', 'int128', 'uint128', 'float32', 'float64', 'float128'] as const;
14
+
15
+ export type Type = (typeof types)[number];
16
+
17
+ export type Valid = Type | Capitalize<Type> | 'char';
15
18
 
16
19
  export const valids = [...types, ...types.map(t => capitalize(t)), 'char'] satisfies Valid[];
17
20
 
18
- export const regex = /^(u?int|float)(8|16|32|64)$/i;
21
+ export const regex = /^(u?int|float)(8|16|32|64|128)$/i;
19
22
 
20
23
  export type Normalize<T extends Valid> = T extends 'char' ? 'uint8' : Uncapitalize<T>;
21
24
 
@@ -36,3 +39,5 @@ export function checkValid(type: { toString(): string }): asserts type is Valid
36
39
  throw new TypeError('Not a valid primitive type: ' + type);
37
40
  }
38
41
  }
42
+
43
+ export const mask64 = BigInt('0xffffffffffffffff');
package/src/requests.ts CHANGED
@@ -201,7 +201,7 @@ export async function set(url: string, data: Uint8Array, options: SetOptions, in
201
201
 
202
202
  if (!options.cacheOnly) await _fetch(new Request(url, init), { method: 'POST' }, true);
203
203
 
204
- resource.add(data, offset).collect();
204
+ resource.add(data, offset);
205
205
  }
206
206
 
207
207
  /**
package/src/struct.ts CHANGED
@@ -107,8 +107,8 @@ export function serialize(instance: unknown): Uint8Array {
107
107
  continue;
108
108
  }
109
109
 
110
- const Type = capitalize(type);
111
- const fn = ('set' + Type) as `set${typeof Type}`;
110
+ const fn = `set${capitalize(type)}` as const;
111
+
112
112
  if (fn == 'setInt64') {
113
113
  view.setBigInt64(iOff, BigInt(value), !options.bigEndian);
114
114
  continue;
@@ -119,6 +119,24 @@ export function serialize(instance: unknown): Uint8Array {
119
119
  continue;
120
120
  }
121
121
 
122
+ if (fn == 'setInt128') {
123
+ view.setBigUint64(iOff + (!options.bigEndian ? 0 : 8), value & primitive.mask64, !options.bigEndian);
124
+ view.setBigInt64(iOff + (!options.bigEndian ? 8 : 0), value >> BigInt(64), !options.bigEndian);
125
+ continue;
126
+ }
127
+
128
+ if (fn == 'setUint128') {
129
+ view.setBigUint64(iOff + (!options.bigEndian ? 0 : 8), value & primitive.mask64, !options.bigEndian);
130
+ view.setBigUint64(iOff + (!options.bigEndian ? 8 : 0), value >> BigInt(64), !options.bigEndian);
131
+ continue;
132
+ }
133
+
134
+ if (fn == 'setFloat128') {
135
+ view.setFloat64(iOff + (!options.bigEndian ? 0 : 8), Number(value), !options.bigEndian);
136
+ view.setBigUint64(iOff + (!options.bigEndian ? 8 : 0), BigInt(0), !options.bigEndian);
137
+ continue;
138
+ }
139
+
122
140
  view[fn](iOff, Number(value), !options.bigEndian);
123
141
  }
124
142
  }
@@ -163,8 +181,7 @@ export function deserialize(instance: unknown, _buffer: ArrayBufferLike | ArrayB
163
181
  object ||= [];
164
182
  }
165
183
 
166
- const Type = capitalize(type);
167
- const fn = ('get' + Type) as `get${typeof Type}`;
184
+ const fn = `get${capitalize(type)}` as const;
168
185
  if (fn == 'getInt64') {
169
186
  object[key] = view.getBigInt64(iOff, !options.bigEndian);
170
187
  continue;
@@ -175,6 +192,25 @@ export function deserialize(instance: unknown, _buffer: ArrayBufferLike | ArrayB
175
192
  continue;
176
193
  }
177
194
 
195
+ if (fn == 'getInt128') {
196
+ object[key] =
197
+ (view.getBigInt64(iOff + (!options.bigEndian ? 8 : 0), !options.bigEndian) << BigInt(64)) |
198
+ view.getBigUint64(iOff + (!options.bigEndian ? 0 : 8), !options.bigEndian);
199
+ continue;
200
+ }
201
+
202
+ if (fn == 'getUint128') {
203
+ object[key] =
204
+ (view.getBigUint64(iOff + (!options.bigEndian ? 8 : 0), !options.bigEndian) << BigInt(64)) |
205
+ view.getBigUint64(iOff + (!options.bigEndian ? 0 : 8), !options.bigEndian);
206
+ continue;
207
+ }
208
+
209
+ if (fn == 'getFloat128') {
210
+ object[key] = view.getFloat64(iOff + (!options.bigEndian ? 0 : 8), !options.bigEndian);
211
+ continue;
212
+ }
213
+
178
214
  object[key] = view[fn](iOff, !options.bigEndian);
179
215
  }
180
216
  }