ordered-binary 1.5.1 → 1.5.3
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/README.md +0 -1
- package/dist/index.cjs +20 -16
- package/index.js +17 -16
- package/package.json +1 -1
- package/tests/test.js +16 -0
package/README.md
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
[](https://www.npmjs.org/package/ordered-binary)
|
|
2
2
|
[](https://www.npmjs.org/package/ordered-binary)
|
|
3
3
|
[](LICENSE)
|
|
4
|
-
<a href="https://dev.doctorevidence.com/"><img src="./assets/powers-dre.png" width="203" /></a>
|
|
5
4
|
|
|
6
5
|
The ordered-binary package provides a representation of JavaScript primitives, serialized into binary format (NodeJS Buffers or Uint8Arrays), such that the binary values are naturally ordered such that it matches the natural ordering or values. For example, since -2.0321 > -2.04, then `toBufferKey(-2.0321)` will be greater than `toBufferKey(-2.04)` as a binary representation, in left-to-right evaluation. This is particular useful for storing keys as binaries with something like LMDB or LevelDB, to avoid any custom sorting.
|
|
7
6
|
|
package/dist/index.cjs
CHANGED
|
@@ -2,8 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
|
-
require('constants');
|
|
6
|
-
|
|
7
5
|
/*
|
|
8
6
|
control character types:
|
|
9
7
|
1 - metadata
|
|
@@ -16,6 +14,9 @@ control character types:
|
|
|
16
14
|
0 - multipart separator
|
|
17
15
|
> 27 normal string characters
|
|
18
16
|
*/
|
|
17
|
+
/*
|
|
18
|
+
* Convert arbitrary scalar values to buffer bytes with type preservation and type-appropriate ordering
|
|
19
|
+
*/
|
|
19
20
|
|
|
20
21
|
const float64Array = new Float64Array(2);
|
|
21
22
|
const int32Array = new Int32Array(float64Array.buffer, 0, 4);
|
|
@@ -68,7 +69,7 @@ function writeKey(key, target, position, inSequence) {
|
|
|
68
69
|
}
|
|
69
70
|
} else {
|
|
70
71
|
if (target.utf8Write)
|
|
71
|
-
position += target.utf8Write(key, position,
|
|
72
|
+
position += target.utf8Write(key, position, target.byteLength - position);
|
|
72
73
|
else
|
|
73
74
|
position += textEncoder.encodeInto(key, target.subarray(position)).written;
|
|
74
75
|
if (position > target.length - 4)
|
|
@@ -176,7 +177,6 @@ function writeKey(key, target, position, inSequence) {
|
|
|
176
177
|
|
|
177
178
|
let position;
|
|
178
179
|
function readKey(buffer, start, end, inSequence) {
|
|
179
|
-
buffer[end] = 0; // make sure it is null terminated
|
|
180
180
|
position = start;
|
|
181
181
|
let controlByte = buffer[position];
|
|
182
182
|
let value;
|
|
@@ -190,7 +190,7 @@ function readKey(buffer, start, end, inSequence) {
|
|
|
190
190
|
} else if (controlByte == 0) {
|
|
191
191
|
value = null;
|
|
192
192
|
} else if (controlByte == 2) {
|
|
193
|
-
value = Symbol.for(
|
|
193
|
+
value = Symbol.for(readStringSafely(buffer, end));
|
|
194
194
|
} else
|
|
195
195
|
return Uint8Array.prototype.slice.call(buffer, start, end)
|
|
196
196
|
} else {
|
|
@@ -209,7 +209,7 @@ function readKey(buffer, start, end, inSequence) {
|
|
|
209
209
|
lowInt = dataView.getInt32(position + 4);
|
|
210
210
|
highInt |= lowInt >>> 28;
|
|
211
211
|
if (size <= 6) { // clear the last bits
|
|
212
|
-
lowInt &= -
|
|
212
|
+
lowInt &= -0x10000;
|
|
213
213
|
}
|
|
214
214
|
lowInt = lowInt << 4;
|
|
215
215
|
if (size > 8) {
|
|
@@ -242,15 +242,7 @@ function readKey(buffer, start, end, inSequence) {
|
|
|
242
242
|
if (controlByte == 27) {
|
|
243
243
|
position++;
|
|
244
244
|
}
|
|
245
|
-
value =
|
|
246
|
-
/*let strStart = position
|
|
247
|
-
let strEnd = end
|
|
248
|
-
for (; position < end; position++) {
|
|
249
|
-
if (buffer[position] == 0) {
|
|
250
|
-
break
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
value = buffer.toString('utf8', strStart, position++)*/
|
|
245
|
+
value = readStringSafely(buffer, end);
|
|
254
246
|
}
|
|
255
247
|
while (position < end) {
|
|
256
248
|
if (buffer[position] === 0)
|
|
@@ -379,7 +371,19 @@ const readString =
|
|
|
379
371
|
'getPosition() { return position },' +
|
|
380
372
|
'readString }'))(fromCharCode)) :
|
|
381
373
|
eval(makeStringBuilder());
|
|
382
|
-
|
|
374
|
+
function readStringSafely(source, end) {
|
|
375
|
+
if (source[end] > 0) {
|
|
376
|
+
let previous = source[end];
|
|
377
|
+
try {
|
|
378
|
+
// read string expects a null terminator, that is a 0 or undefined from reading past the end of the buffer, so we
|
|
379
|
+
// have to ensure that, but do so safely, restoring the buffer to its original state
|
|
380
|
+
source[end] = 0;
|
|
381
|
+
return readString(source)
|
|
382
|
+
} finally {
|
|
383
|
+
source[end] = previous;
|
|
384
|
+
}
|
|
385
|
+
} else return readString(source);
|
|
386
|
+
}
|
|
383
387
|
function compareKeys(a, b) {
|
|
384
388
|
// compare with type consistency that matches binary comparison
|
|
385
389
|
if (typeof a == 'object') {
|
package/index.js
CHANGED
|
@@ -14,8 +14,6 @@ control character types:
|
|
|
14
14
|
* Convert arbitrary scalar values to buffer bytes with type preservation and type-appropriate ordering
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
import exp from "constants"
|
|
18
|
-
|
|
19
17
|
const float64Array = new Float64Array(2)
|
|
20
18
|
const int32Array = new Int32Array(float64Array.buffer, 0, 4)
|
|
21
19
|
let nullTerminate = false
|
|
@@ -67,7 +65,7 @@ export function writeKey(key, target, position, inSequence) {
|
|
|
67
65
|
}
|
|
68
66
|
} else {
|
|
69
67
|
if (target.utf8Write)
|
|
70
|
-
position += target.utf8Write(key, position,
|
|
68
|
+
position += target.utf8Write(key, position, target.byteLength - position)
|
|
71
69
|
else
|
|
72
70
|
position += textEncoder.encodeInto(key, target.subarray(position)).written
|
|
73
71
|
if (position > target.length - 4)
|
|
@@ -175,7 +173,6 @@ export function writeKey(key, target, position, inSequence) {
|
|
|
175
173
|
|
|
176
174
|
let position
|
|
177
175
|
export function readKey(buffer, start, end, inSequence) {
|
|
178
|
-
buffer[end] = 0 // make sure it is null terminated
|
|
179
176
|
position = start
|
|
180
177
|
let controlByte = buffer[position]
|
|
181
178
|
let value
|
|
@@ -189,7 +186,7 @@ export function readKey(buffer, start, end, inSequence) {
|
|
|
189
186
|
} else if (controlByte == 0) {
|
|
190
187
|
value = null
|
|
191
188
|
} else if (controlByte == 2) {
|
|
192
|
-
value = Symbol.for(
|
|
189
|
+
value = Symbol.for(readStringSafely(buffer, end))
|
|
193
190
|
} else
|
|
194
191
|
return Uint8Array.prototype.slice.call(buffer, start, end)
|
|
195
192
|
} else {
|
|
@@ -208,7 +205,7 @@ export function readKey(buffer, start, end, inSequence) {
|
|
|
208
205
|
lowInt = dataView.getInt32(position + 4)
|
|
209
206
|
highInt |= lowInt >>> 28
|
|
210
207
|
if (size <= 6) { // clear the last bits
|
|
211
|
-
lowInt &= -
|
|
208
|
+
lowInt &= -0x10000
|
|
212
209
|
}
|
|
213
210
|
lowInt = lowInt << 4
|
|
214
211
|
if (size > 8) {
|
|
@@ -241,15 +238,7 @@ export function readKey(buffer, start, end, inSequence) {
|
|
|
241
238
|
if (controlByte == 27) {
|
|
242
239
|
position++
|
|
243
240
|
}
|
|
244
|
-
value =
|
|
245
|
-
/*let strStart = position
|
|
246
|
-
let strEnd = end
|
|
247
|
-
for (; position < end; position++) {
|
|
248
|
-
if (buffer[position] == 0) {
|
|
249
|
-
break
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
value = buffer.toString('utf8', strStart, position++)*/
|
|
241
|
+
value = readStringSafely(buffer, end)
|
|
253
242
|
}
|
|
254
243
|
while (position < end) {
|
|
255
244
|
if (buffer[position] === 0)
|
|
@@ -378,7 +367,19 @@ const readString =
|
|
|
378
367
|
'getPosition() { return position },' +
|
|
379
368
|
'readString }'))(fromCharCode)) :
|
|
380
369
|
eval(makeStringBuilder())
|
|
381
|
-
|
|
370
|
+
function readStringSafely(source, end) {
|
|
371
|
+
if (source[end] > 0) {
|
|
372
|
+
let previous = source[end]
|
|
373
|
+
try {
|
|
374
|
+
// read string expects a null terminator, that is a 0 or undefined from reading past the end of the buffer, so we
|
|
375
|
+
// have to ensure that, but do so safely, restoring the buffer to its original state
|
|
376
|
+
source[end] = 0
|
|
377
|
+
return readString(source)
|
|
378
|
+
} finally {
|
|
379
|
+
source[end] = previous
|
|
380
|
+
}
|
|
381
|
+
} else return readString(source);
|
|
382
|
+
}
|
|
382
383
|
export function compareKeys(a, b) {
|
|
383
384
|
// compare with type consistency that matches binary comparison
|
|
384
385
|
if (typeof a == 'object') {
|
package/package.json
CHANGED
package/tests/test.js
CHANGED
|
@@ -27,6 +27,7 @@ suite('key buffers', () => {
|
|
|
27
27
|
assert.strictEqual(fromBufferKey(toBufferKey(-4)), -4)
|
|
28
28
|
assert.strictEqual(fromBufferKey(toBufferKey(3.4)), 3.4)
|
|
29
29
|
assert.strictEqual(fromBufferKey(toBufferKey(Math.PI)), Math.PI)
|
|
30
|
+
assert.strictEqual(fromBufferKey(toBufferKey(2002225)), 2002225)
|
|
30
31
|
assert.strictEqual(fromBufferKey(toBufferKey(9377288)), 9377288)
|
|
31
32
|
assert.strictEqual(fromBufferKey(toBufferKey(1503579323825)), 1503579323825)
|
|
32
33
|
assert.strictEqual(fromBufferKey(toBufferKey(1503579323825.3523532)), 1503579323825.3523532)
|
|
@@ -35,6 +36,18 @@ suite('key buffers', () => {
|
|
|
35
36
|
assert.strictEqual(fromBufferKey(toBufferKey(-0.00005032)), -0.00005032)
|
|
36
37
|
assert.strictEqual(fromBufferKey(toBufferKey(0.00000000000000000000000005431)), 0.00000000000000000000000005431)
|
|
37
38
|
})
|
|
39
|
+
test('within buffer equivalence', () => {
|
|
40
|
+
let buffer = Buffer.alloc(1024, 0xff);
|
|
41
|
+
let length = writeKey(2002225, buffer, 0);
|
|
42
|
+
let position = length;
|
|
43
|
+
buffer[position++] = 0xff;
|
|
44
|
+
buffer[position++] = 0xff;
|
|
45
|
+
assert.strictEqual(readKey(buffer, 0, length), 2002225);
|
|
46
|
+
length = writeKey('hello, world', buffer, 0);
|
|
47
|
+
assert.strictEqual(readKey(buffer, 0, length), 'hello, world');
|
|
48
|
+
// ensure that reading the string didn't modify the buffer after the string (or is restored at least)
|
|
49
|
+
assert.strictEqual(buffer[length], 0xff);
|
|
50
|
+
});
|
|
38
51
|
test('number comparison', () => {
|
|
39
52
|
assertBufferComparison(toBufferKey(4), toBufferKey(5))
|
|
40
53
|
assertBufferComparison(toBufferKey(1503579323824), toBufferKey(1503579323825))
|
|
@@ -68,6 +81,9 @@ suite('key buffers', () => {
|
|
|
68
81
|
test('bigint comparison', () => {
|
|
69
82
|
assertBufferComparison(toBufferKey(0xfffffffffffffffffffffn), toBufferKey(0x100fffffffffffffffffffn))
|
|
70
83
|
assertBufferComparison(toBufferKey(12345678901234567890), toBufferKey(12345678901234567890n))
|
|
84
|
+
assertBufferComparison(toBufferKey(6135421331404949076605986n), toBufferKey(6135421331404949076605987n))
|
|
85
|
+
assertBufferComparison(toBufferKey(-6135421331404949076605986n), toBufferKey(-6135421331404949076605985n))
|
|
86
|
+
assertBufferComparison(toBufferKey(-35913040084491349n), toBufferKey(-35913040084491348n))
|
|
71
87
|
})
|
|
72
88
|
|
|
73
89
|
test('string equivalence', () => {
|