@nxtedition/slice 1.1.4 → 1.1.6
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 +122 -34
- 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)
|
|
@@ -171,7 +209,13 @@ export class Slice {
|
|
|
171
209
|
offset += this.byteOffset
|
|
172
210
|
}
|
|
173
211
|
|
|
174
|
-
|
|
212
|
+
const available = this.byteOffset + this.byteLength - offset
|
|
213
|
+
if (available <= 0) {
|
|
214
|
+
return
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
const end = source.byteLength < available ? source.byteLength : available
|
|
218
|
+
source.copy(this.buffer, offset, 0, end)
|
|
175
219
|
}
|
|
176
220
|
|
|
177
221
|
at(index ) {
|
|
@@ -190,6 +234,8 @@ export class Slice {
|
|
|
190
234
|
}
|
|
191
235
|
|
|
192
236
|
toString(encoding , start , end ) {
|
|
237
|
+
const sliceEnd = this.byteOffset + this.byteLength
|
|
238
|
+
|
|
193
239
|
if (start === undefined) {
|
|
194
240
|
start = this.byteOffset
|
|
195
241
|
} else {
|
|
@@ -197,15 +243,21 @@ export class Slice {
|
|
|
197
243
|
}
|
|
198
244
|
|
|
199
245
|
if (end === undefined) {
|
|
200
|
-
end =
|
|
246
|
+
end = sliceEnd
|
|
201
247
|
} else {
|
|
202
248
|
end += this.byteOffset
|
|
203
249
|
}
|
|
204
250
|
|
|
251
|
+
if (end > sliceEnd) {
|
|
252
|
+
end = sliceEnd
|
|
253
|
+
}
|
|
254
|
+
|
|
205
255
|
return this.buffer.toString(encoding, start, end)
|
|
206
256
|
}
|
|
207
257
|
|
|
208
258
|
toBuffer(start , end ) {
|
|
259
|
+
const sliceEnd = this.byteOffset + this.byteLength
|
|
260
|
+
|
|
209
261
|
if (start === undefined) {
|
|
210
262
|
start = this.byteOffset
|
|
211
263
|
} else {
|
|
@@ -213,30 +265,45 @@ export class Slice {
|
|
|
213
265
|
}
|
|
214
266
|
|
|
215
267
|
if (end === undefined) {
|
|
216
|
-
end =
|
|
268
|
+
end = sliceEnd
|
|
217
269
|
} else {
|
|
218
270
|
end += this.byteOffset
|
|
219
271
|
}
|
|
220
272
|
|
|
273
|
+
if (end > sliceEnd) {
|
|
274
|
+
end = sliceEnd
|
|
275
|
+
}
|
|
276
|
+
|
|
221
277
|
return start === 0 && end === this.buffer.byteLength
|
|
222
278
|
? this.buffer
|
|
223
279
|
: this.buffer.subarray(start, end)
|
|
224
280
|
}
|
|
225
281
|
|
|
226
282
|
get [Symbol.toStringTag]() {
|
|
227
|
-
return
|
|
283
|
+
return 'Slice'
|
|
228
284
|
}
|
|
229
285
|
|
|
230
|
-
[util.inspect.custom](
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
for (let i = 0; i <
|
|
237
|
-
|
|
286
|
+
[util.inspect.custom]() {
|
|
287
|
+
const MAX_BYTES = 32
|
|
288
|
+
const len = this.byteLength
|
|
289
|
+
const shown = len < MAX_BYTES ? len : MAX_BYTES
|
|
290
|
+
|
|
291
|
+
let hex = ''
|
|
292
|
+
for (let i = 0; i < shown; i++) {
|
|
293
|
+
if (i !== 0) {
|
|
294
|
+
hex += ' '
|
|
295
|
+
}
|
|
296
|
+
hex += this.buffer[this.byteOffset + i].toString(16).padStart(2, '0')
|
|
238
297
|
}
|
|
239
|
-
|
|
298
|
+
if (shown < len) {
|
|
299
|
+
hex += ` ... (${len - shown} more)`
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
const strEnd = shown < len ? this.byteOffset + shown : this.byteOffset + len
|
|
303
|
+
const str = this.buffer.toString('utf8', this.byteOffset, strEnd)
|
|
304
|
+
const truncated = shown < len ? '…' : ''
|
|
305
|
+
|
|
306
|
+
return `Slice(${len}): "${str}${truncated}" <${hex}>`
|
|
240
307
|
}
|
|
241
308
|
}
|
|
242
309
|
|
|
@@ -251,8 +318,32 @@ export class PoolAllocator {
|
|
|
251
318
|
#poolSize = 0
|
|
252
319
|
#poolCount = 0
|
|
253
320
|
|
|
254
|
-
constructor(
|
|
255
|
-
|
|
321
|
+
constructor(
|
|
322
|
+
poolTotalOrBuffer = 128 *
|
|
323
|
+
1024 *
|
|
324
|
+
1024,
|
|
325
|
+
) {
|
|
326
|
+
if (typeof poolTotalOrBuffer === 'number') {
|
|
327
|
+
this.#poolBuffer = Buffer.allocUnsafeSlow(poolTotalOrBuffer)
|
|
328
|
+
} else if (poolTotalOrBuffer instanceof Buffer) {
|
|
329
|
+
this.#poolBuffer = poolTotalOrBuffer
|
|
330
|
+
} else if (ArrayBuffer.isView(poolTotalOrBuffer)) {
|
|
331
|
+
this.#poolBuffer = Buffer.from(
|
|
332
|
+
poolTotalOrBuffer.buffer,
|
|
333
|
+
poolTotalOrBuffer.byteOffset,
|
|
334
|
+
poolTotalOrBuffer.byteLength,
|
|
335
|
+
)
|
|
336
|
+
} else if (
|
|
337
|
+
poolTotalOrBuffer instanceof ArrayBuffer ||
|
|
338
|
+
poolTotalOrBuffer instanceof SharedArrayBuffer
|
|
339
|
+
) {
|
|
340
|
+
this.#poolBuffer = Buffer.from(poolTotalOrBuffer)
|
|
341
|
+
} else {
|
|
342
|
+
throw new TypeError(
|
|
343
|
+
'Invalid poolTotalOrBuffer: must be a Buffer, ArrayBufferView, ArrayBuffer, SharedArrayBuffer, or number',
|
|
344
|
+
)
|
|
345
|
+
}
|
|
346
|
+
|
|
256
347
|
for (let n = 0; 2 ** n <= 256 * 1024; n++) {
|
|
257
348
|
this.#poolsBucket.push([])
|
|
258
349
|
this.#poolsBucketUsed.push(0)
|
|
@@ -279,9 +370,13 @@ export class PoolAllocator {
|
|
|
279
370
|
throw new TypeError(`Invalid byteLength: ${byteLength}`)
|
|
280
371
|
}
|
|
281
372
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
373
|
+
// 2^30 is the largest power-of-two that fits a 32-bit signed int; a
|
|
374
|
+
// larger request overflows `1 << dstIdx` to a negative bucket size.
|
|
375
|
+
if (byteLength > 1 << 30) {
|
|
376
|
+
throw new RangeError(`byteLength too large: ${byteLength} (max ${1 << 30})`)
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
if (slice.byteLength === byteLength) {
|
|
285
380
|
return slice
|
|
286
381
|
}
|
|
287
382
|
|
|
@@ -317,15 +412,8 @@ export class PoolAllocator {
|
|
|
317
412
|
}
|
|
318
413
|
|
|
319
414
|
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
415
|
|
|
328
|
-
if (dstIdx < this.#poolsBucket.length && this.#poolsBucket[dstIdx]
|
|
416
|
+
if (dstIdx < this.#poolsBucket.length && this.#poolsBucket[dstIdx].length) {
|
|
329
417
|
slice.buffer = this.#poolBuffer
|
|
330
418
|
slice.byteOffset = this.#poolsBucket[dstIdx].pop()
|
|
331
419
|
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.6",
|
|
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": "472a4cdfd11ff9f1a7dcf8b81599bc1d9270bc90"
|
|
34
34
|
}
|