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 +5 -9
- package/dist/cache.js +36 -12
- package/dist/internal/primitives.d.ts +5 -3
- package/dist/internal/primitives.js +3 -2
- package/dist/requests.js +1 -1
- package/dist/struct.js +33 -4
- package/package.json +1 -1
- package/src/cache.ts +41 -10
- package/src/internal/primitives.ts +9 -4
- package/src/requests.ts +1 -1
- package/src/struct.ts +40 -4
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
|
-
|
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
|
-
|
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.
|
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(
|
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
|
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
|
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)
|
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
|
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
|
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
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
|
-
|
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(
|
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']
|
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)
|
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
|
111
|
-
|
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
|
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
|
}
|