@nxtedition/slice 1.1.4 → 1.1.5
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/lib/index.d.ts +3 -3
- package/lib/index.js +115 -33
- package/package.json +2 -2
package/lib/index.d.ts
CHANGED
|
@@ -9,7 +9,7 @@ export declare class Slice {
|
|
|
9
9
|
byteOffset: number;
|
|
10
10
|
byteLength: number;
|
|
11
11
|
maxByteLength: number;
|
|
12
|
-
static EMPTY_BUF: Buffer;
|
|
12
|
+
static get EMPTY_BUF(): Buffer;
|
|
13
13
|
constructor(buffer?: Buffer<ArrayBufferLike>, byteOffset?: number, byteLength?: number, maxByteLength?: number);
|
|
14
14
|
reset(): void;
|
|
15
15
|
get length(): number;
|
|
@@ -24,11 +24,11 @@ export declare class Slice {
|
|
|
24
24
|
toString(encoding?: BufferEncoding, start?: number, end?: number): string;
|
|
25
25
|
toBuffer(start?: number, end?: number): Buffer;
|
|
26
26
|
get [Symbol.toStringTag](): string;
|
|
27
|
-
[util.inspect.custom](
|
|
27
|
+
[util.inspect.custom](): string;
|
|
28
28
|
}
|
|
29
29
|
export declare class PoolAllocator {
|
|
30
30
|
#private;
|
|
31
|
-
constructor(
|
|
31
|
+
constructor(poolTotalOrBuffer?: Buffer | ArrayBufferView | ArrayBuffer | SharedArrayBuffer | number);
|
|
32
32
|
get size(): number;
|
|
33
33
|
isFromPool(slice: Slice | null | undefined): boolean;
|
|
34
34
|
realloc(byteLength: number): Slice;
|
package/lib/index.js
CHANGED
|
@@ -14,7 +14,9 @@ export class Slice {
|
|
|
14
14
|
byteLength = 0
|
|
15
15
|
maxByteLength = 0
|
|
16
16
|
|
|
17
|
-
static EMPTY_BUF
|
|
17
|
+
static get EMPTY_BUF() {
|
|
18
|
+
return EMPTY_BUF
|
|
19
|
+
}
|
|
18
20
|
|
|
19
21
|
constructor(
|
|
20
22
|
buffer = Slice.EMPTY_BUF,
|
|
@@ -71,6 +73,8 @@ export class Slice {
|
|
|
71
73
|
sourceStart ,
|
|
72
74
|
sourceEnd ,
|
|
73
75
|
) {
|
|
76
|
+
const sliceEnd = this.byteOffset + this.byteLength
|
|
77
|
+
|
|
74
78
|
if (sourceStart === undefined) {
|
|
75
79
|
sourceStart = this.byteOffset
|
|
76
80
|
} else {
|
|
@@ -78,15 +82,19 @@ export class Slice {
|
|
|
78
82
|
}
|
|
79
83
|
|
|
80
84
|
if (sourceEnd === undefined) {
|
|
81
|
-
sourceEnd =
|
|
85
|
+
sourceEnd = sliceEnd
|
|
82
86
|
} else {
|
|
83
87
|
sourceEnd += this.byteOffset
|
|
84
88
|
}
|
|
85
89
|
|
|
86
|
-
|
|
90
|
+
// Clamp against the logical slice length so copy() cannot read past
|
|
91
|
+
// the slice's own end and leak adjacent (pool) memory.
|
|
92
|
+
if (sourceEnd > sliceEnd) {
|
|
93
|
+
sourceEnd = sliceEnd
|
|
94
|
+
}
|
|
87
95
|
|
|
88
96
|
if (target instanceof Slice) {
|
|
89
|
-
targetEnd = target.byteOffset + target.byteLength
|
|
97
|
+
const targetEnd = target.byteOffset + target.byteLength
|
|
90
98
|
if (targetStart === undefined) {
|
|
91
99
|
targetStart = target.byteOffset
|
|
92
100
|
} else {
|
|
@@ -94,7 +102,9 @@ export class Slice {
|
|
|
94
102
|
}
|
|
95
103
|
|
|
96
104
|
target = target.buffer
|
|
97
|
-
|
|
105
|
+
if (sourceEnd - sourceStart > targetEnd - targetStart) {
|
|
106
|
+
sourceEnd = sourceStart + (targetEnd - targetStart)
|
|
107
|
+
}
|
|
98
108
|
}
|
|
99
109
|
|
|
100
110
|
if (
|
|
@@ -115,7 +125,20 @@ export class Slice {
|
|
|
115
125
|
sourceStart ,
|
|
116
126
|
sourceEnd ,
|
|
117
127
|
) {
|
|
128
|
+
if (
|
|
129
|
+
target === this &&
|
|
130
|
+
targetStart === undefined &&
|
|
131
|
+
targetEnd === undefined &&
|
|
132
|
+
sourceStart === undefined &&
|
|
133
|
+
sourceEnd === undefined
|
|
134
|
+
) {
|
|
135
|
+
return 0
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const sliceEnd = this.byteOffset + this.byteLength
|
|
139
|
+
|
|
118
140
|
if (target instanceof Slice) {
|
|
141
|
+
const targetSliceEnd = target.byteOffset + target.byteLength
|
|
119
142
|
if (targetStart === undefined) {
|
|
120
143
|
targetStart = target.byteOffset
|
|
121
144
|
} else {
|
|
@@ -123,11 +146,14 @@ export class Slice {
|
|
|
123
146
|
}
|
|
124
147
|
|
|
125
148
|
if (targetEnd === undefined) {
|
|
126
|
-
targetEnd =
|
|
149
|
+
targetEnd = targetSliceEnd
|
|
127
150
|
} else {
|
|
128
151
|
targetEnd += target.byteOffset
|
|
129
152
|
}
|
|
130
153
|
|
|
154
|
+
if (targetEnd > targetSliceEnd) {
|
|
155
|
+
targetEnd = targetSliceEnd
|
|
156
|
+
}
|
|
131
157
|
target = target.buffer
|
|
132
158
|
}
|
|
133
159
|
|
|
@@ -138,23 +164,35 @@ export class Slice {
|
|
|
138
164
|
}
|
|
139
165
|
|
|
140
166
|
if (sourceEnd === undefined) {
|
|
141
|
-
sourceEnd =
|
|
167
|
+
sourceEnd = sliceEnd
|
|
142
168
|
} else {
|
|
143
169
|
sourceEnd += this.byteOffset
|
|
144
170
|
}
|
|
145
171
|
|
|
172
|
+
if (sourceEnd > sliceEnd) {
|
|
173
|
+
sourceEnd = sliceEnd
|
|
174
|
+
}
|
|
175
|
+
|
|
146
176
|
return this.buffer.compare(target, targetStart, targetEnd, sourceStart, sourceEnd)
|
|
147
177
|
}
|
|
148
178
|
|
|
149
179
|
write(string , offset , length , encoding ) {
|
|
180
|
+
const sliceEnd = this.byteOffset + this.byteLength
|
|
181
|
+
|
|
150
182
|
if (offset === undefined) {
|
|
151
183
|
offset = this.byteOffset
|
|
152
184
|
} else {
|
|
185
|
+
if (offset < 0 || offset > this.byteLength) {
|
|
186
|
+
throw new RangeError(`Invalid offset: ${offset}`)
|
|
187
|
+
}
|
|
153
188
|
offset += this.byteOffset
|
|
154
189
|
}
|
|
155
190
|
|
|
191
|
+
const available = sliceEnd - offset
|
|
156
192
|
if (length === undefined) {
|
|
157
|
-
length =
|
|
193
|
+
length = available
|
|
194
|
+
} else if (length > available) {
|
|
195
|
+
length = available
|
|
158
196
|
}
|
|
159
197
|
|
|
160
198
|
return this.buffer.write(string, offset, length, encoding)
|
|
@@ -190,6 +228,8 @@ export class Slice {
|
|
|
190
228
|
}
|
|
191
229
|
|
|
192
230
|
toString(encoding , start , end ) {
|
|
231
|
+
const sliceEnd = this.byteOffset + this.byteLength
|
|
232
|
+
|
|
193
233
|
if (start === undefined) {
|
|
194
234
|
start = this.byteOffset
|
|
195
235
|
} else {
|
|
@@ -197,15 +237,21 @@ export class Slice {
|
|
|
197
237
|
}
|
|
198
238
|
|
|
199
239
|
if (end === undefined) {
|
|
200
|
-
end =
|
|
240
|
+
end = sliceEnd
|
|
201
241
|
} else {
|
|
202
242
|
end += this.byteOffset
|
|
203
243
|
}
|
|
204
244
|
|
|
245
|
+
if (end > sliceEnd) {
|
|
246
|
+
end = sliceEnd
|
|
247
|
+
}
|
|
248
|
+
|
|
205
249
|
return this.buffer.toString(encoding, start, end)
|
|
206
250
|
}
|
|
207
251
|
|
|
208
252
|
toBuffer(start , end ) {
|
|
253
|
+
const sliceEnd = this.byteOffset + this.byteLength
|
|
254
|
+
|
|
209
255
|
if (start === undefined) {
|
|
210
256
|
start = this.byteOffset
|
|
211
257
|
} else {
|
|
@@ -213,30 +259,45 @@ export class Slice {
|
|
|
213
259
|
}
|
|
214
260
|
|
|
215
261
|
if (end === undefined) {
|
|
216
|
-
end =
|
|
262
|
+
end = sliceEnd
|
|
217
263
|
} else {
|
|
218
264
|
end += this.byteOffset
|
|
219
265
|
}
|
|
220
266
|
|
|
267
|
+
if (end > sliceEnd) {
|
|
268
|
+
end = sliceEnd
|
|
269
|
+
}
|
|
270
|
+
|
|
221
271
|
return start === 0 && end === this.buffer.byteLength
|
|
222
272
|
? this.buffer
|
|
223
273
|
: this.buffer.subarray(start, end)
|
|
224
274
|
}
|
|
225
275
|
|
|
226
276
|
get [Symbol.toStringTag]() {
|
|
227
|
-
return
|
|
277
|
+
return 'Slice'
|
|
228
278
|
}
|
|
229
279
|
|
|
230
|
-
[util.inspect.custom](
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
for (let i = 0; i <
|
|
237
|
-
|
|
280
|
+
[util.inspect.custom]() {
|
|
281
|
+
const MAX_BYTES = 32
|
|
282
|
+
const len = this.byteLength
|
|
283
|
+
const shown = len < MAX_BYTES ? len : MAX_BYTES
|
|
284
|
+
|
|
285
|
+
let hex = ''
|
|
286
|
+
for (let i = 0; i < shown; i++) {
|
|
287
|
+
if (i !== 0) {
|
|
288
|
+
hex += ' '
|
|
289
|
+
}
|
|
290
|
+
hex += this.buffer[this.byteOffset + i].toString(16).padStart(2, '0')
|
|
291
|
+
}
|
|
292
|
+
if (shown < len) {
|
|
293
|
+
hex += ` ... (${len - shown} more)`
|
|
238
294
|
}
|
|
239
|
-
|
|
295
|
+
|
|
296
|
+
const strEnd = shown < len ? this.byteOffset + shown : this.byteOffset + len
|
|
297
|
+
const str = this.buffer.toString('utf8', this.byteOffset, strEnd)
|
|
298
|
+
const truncated = shown < len ? '…' : ''
|
|
299
|
+
|
|
300
|
+
return `Slice(${len}): "${str}${truncated}" <${hex}>`
|
|
240
301
|
}
|
|
241
302
|
}
|
|
242
303
|
|
|
@@ -251,8 +312,32 @@ export class PoolAllocator {
|
|
|
251
312
|
#poolSize = 0
|
|
252
313
|
#poolCount = 0
|
|
253
314
|
|
|
254
|
-
constructor(
|
|
255
|
-
|
|
315
|
+
constructor(
|
|
316
|
+
poolTotalOrBuffer = 128 *
|
|
317
|
+
1024 *
|
|
318
|
+
1024,
|
|
319
|
+
) {
|
|
320
|
+
if (typeof poolTotalOrBuffer === 'number') {
|
|
321
|
+
this.#poolBuffer = Buffer.allocUnsafeSlow(poolTotalOrBuffer)
|
|
322
|
+
} else if (poolTotalOrBuffer instanceof Buffer) {
|
|
323
|
+
this.#poolBuffer = poolTotalOrBuffer
|
|
324
|
+
} else if (ArrayBuffer.isView(poolTotalOrBuffer)) {
|
|
325
|
+
this.#poolBuffer = Buffer.from(
|
|
326
|
+
poolTotalOrBuffer.buffer,
|
|
327
|
+
poolTotalOrBuffer.byteOffset,
|
|
328
|
+
poolTotalOrBuffer.byteLength,
|
|
329
|
+
)
|
|
330
|
+
} else if (
|
|
331
|
+
poolTotalOrBuffer instanceof ArrayBuffer ||
|
|
332
|
+
poolTotalOrBuffer instanceof SharedArrayBuffer
|
|
333
|
+
) {
|
|
334
|
+
this.#poolBuffer = Buffer.from(poolTotalOrBuffer)
|
|
335
|
+
} else {
|
|
336
|
+
throw new TypeError(
|
|
337
|
+
'Invalid poolTotalOrBuffer: must be a Buffer, ArrayBufferView, ArrayBuffer, SharedArrayBuffer, or number',
|
|
338
|
+
)
|
|
339
|
+
}
|
|
340
|
+
|
|
256
341
|
for (let n = 0; 2 ** n <= 256 * 1024; n++) {
|
|
257
342
|
this.#poolsBucket.push([])
|
|
258
343
|
this.#poolsBucketUsed.push(0)
|
|
@@ -279,9 +364,13 @@ export class PoolAllocator {
|
|
|
279
364
|
throw new TypeError(`Invalid byteLength: ${byteLength}`)
|
|
280
365
|
}
|
|
281
366
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
367
|
+
// 2^30 is the largest power-of-two that fits a 32-bit signed int; a
|
|
368
|
+
// larger request overflows `1 << dstIdx` to a negative bucket size.
|
|
369
|
+
if (byteLength > 1 << 30) {
|
|
370
|
+
throw new RangeError(`byteLength too large: ${byteLength} (max ${1 << 30})`)
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
if (slice.byteLength === byteLength) {
|
|
285
374
|
return slice
|
|
286
375
|
}
|
|
287
376
|
|
|
@@ -317,15 +406,8 @@ export class PoolAllocator {
|
|
|
317
406
|
}
|
|
318
407
|
|
|
319
408
|
const maxByteLength = 1 << dstIdx
|
|
320
|
-
if (
|
|
321
|
-
this.#poolsBucket.length > 32 ||
|
|
322
|
-
maxByteLength < byteLength ||
|
|
323
|
-
(maxByteLength & 0x7) !== 0
|
|
324
|
-
) {
|
|
325
|
-
throw new Error(`Invalid pool state`)
|
|
326
|
-
}
|
|
327
409
|
|
|
328
|
-
if (dstIdx < this.#poolsBucket.length && this.#poolsBucket[dstIdx]
|
|
410
|
+
if (dstIdx < this.#poolsBucket.length && this.#poolsBucket[dstIdx].length) {
|
|
329
411
|
slice.buffer = this.#poolBuffer
|
|
330
412
|
slice.byteOffset = this.#poolsBucket[dstIdx].pop()
|
|
331
413
|
slice.byteLength = byteLength
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nxtedition/slice",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.5",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "lib/index.d.ts",
|
|
@@ -30,5 +30,5 @@
|
|
|
30
30
|
"tsd": "^0.33.0",
|
|
31
31
|
"typescript": "^5.9.3"
|
|
32
32
|
},
|
|
33
|
-
"gitHead": "
|
|
33
|
+
"gitHead": "b3ff34d7bea69e295919bdfdae8bc2e6ff9ab0ff"
|
|
34
34
|
}
|