utilium 1.2.8 → 1.2.10

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,25 @@ 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>);
49
+ id: ID, _size: number, options: Options, resources?: Map<ID, Resource<ID> | undefined>);
50
50
  /** Combines adjacent regions and combines adjacent ranges within a region */
51
51
  collect(): void;
52
52
  /** Takes an initial range and finds the sub-ranges that are not in the cache */
53
53
  missing(start: number, end: number): Range[];
54
+ /**
55
+ * Get the cached sub-ranges of an initial range.
56
+ * This is conceptually the inverse of `missing`.
57
+ */
58
+ cached(start: number, end: number): Range[];
54
59
  /** Get the region who's ranges include an offset */
55
60
  regionAt(offset: number): Region | undefined;
56
61
  /** Add new data to the cache at given specified offset */
package/dist/cache.js CHANGED
@@ -6,21 +6,49 @@ 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
54
  /** Combines adjacent regions and combines adjacent ranges within a region */
@@ -83,6 +111,39 @@ export class Resource {
83
111
  missingRanges.push({ start, end });
84
112
  return missingRanges;
85
113
  }
114
+ /**
115
+ * Get the cached sub-ranges of an initial range.
116
+ * This is conceptually the inverse of `missing`.
117
+ */
118
+ cached(start, end) {
119
+ const cachedRanges = [];
120
+ for (const region of this.regions) {
121
+ if (region.offset >= end)
122
+ break;
123
+ for (const range of region.ranges) {
124
+ if (range.end <= start)
125
+ continue;
126
+ if (range.start >= end)
127
+ break;
128
+ cachedRanges.push({
129
+ start: Math.max(start, range.start),
130
+ end: Math.min(end, range.end),
131
+ });
132
+ }
133
+ }
134
+ cachedRanges.sort((a, b) => a.start - b.start);
135
+ const merged = [];
136
+ for (const curr of cachedRanges) {
137
+ const last = merged.at(-1);
138
+ if (last && curr.start <= last.end) {
139
+ last.end = Math.max(last.end, curr.end);
140
+ }
141
+ else {
142
+ merged.push(curr);
143
+ }
144
+ }
145
+ return merged;
146
+ }
86
147
  /** Get the region who's ranges include an offset */
87
148
  regionAt(offset) {
88
149
  if (!this.regions.length)
@@ -104,6 +165,7 @@ export class Resource {
104
165
  region.data.set(data, offset);
105
166
  region.ranges.push({ start: offset, end });
106
167
  region.ranges.sort((a, b) => a.start - b.start);
168
+ this.collect();
107
169
  return this;
108
170
  }
109
171
  // Find the correct index to insert the new region
@@ -116,6 +178,7 @@ export class Resource {
116
178
  else {
117
179
  this.regions.splice(insertIndex, 0, newRegion); // Insert before the first region with a greater offset
118
180
  }
181
+ this.collect();
119
182
  return this;
120
183
  }
121
184
  }
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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "utilium",
3
- "version": "1.2.8",
3
+ "version": "1.2.10",
4
4
  "description": "Typescript utilities",
5
5
  "funding": {
6
6
  "type": "individual",
package/src/cache.ts CHANGED
@@ -45,16 +45,52 @@ 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
  }
@@ -105,7 +141,6 @@ export class Resource<ID> {
105
141
 
106
142
  for (const range of region.ranges) {
107
143
  if (range.end <= start) continue;
108
-
109
144
  if (range.start >= end) break;
110
145
 
111
146
  if (range.start > start) {
@@ -127,6 +162,41 @@ export class Resource<ID> {
127
162
  return missingRanges;
128
163
  }
129
164
 
165
+ /**
166
+ * Get the cached sub-ranges of an initial range.
167
+ * This is conceptually the inverse of `missing`.
168
+ */
169
+ public cached(start: number, end: number): Range[] {
170
+ const cachedRanges: Range[] = [];
171
+
172
+ for (const region of this.regions) {
173
+ if (region.offset >= end) break;
174
+
175
+ for (const range of region.ranges) {
176
+ if (range.end <= start) continue;
177
+ if (range.start >= end) break;
178
+
179
+ cachedRanges.push({
180
+ start: Math.max(start, range.start),
181
+ end: Math.min(end, range.end),
182
+ });
183
+ }
184
+ }
185
+
186
+ cachedRanges.sort((a, b) => a.start - b.start);
187
+ const merged: Range[] = [];
188
+ for (const curr of cachedRanges) {
189
+ const last = merged.at(-1);
190
+ if (last && curr.start <= last.end) {
191
+ last.end = Math.max(last.end, curr.end);
192
+ } else {
193
+ merged.push(curr);
194
+ }
195
+ }
196
+
197
+ return merged;
198
+ }
199
+
130
200
  /** Get the region who's ranges include an offset */
131
201
  public regionAt(offset: number): Region | undefined {
132
202
  if (!this.regions.length) return;
@@ -150,6 +220,7 @@ export class Resource<ID> {
150
220
  region.ranges.push({ start: offset, end });
151
221
  region.ranges.sort((a, b) => a.start - b.start);
152
222
 
223
+ this.collect();
153
224
  return this;
154
225
  }
155
226
 
@@ -164,6 +235,7 @@ export class Resource<ID> {
164
235
  this.regions.splice(insertIndex, 0, newRegion); // Insert before the first region with a greater offset
165
236
  }
166
237
 
238
+ this.collect();
167
239
  return this;
168
240
  }
169
241
  }
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
  /**