Comparing version 1.0.2 to 1.0.3
@@ -12,202 +12,81 @@ 'use strict'; | ||
describe('Internal bytes list', () => { | ||
it('sets bits, individually incremented', () => { | ||
const bl$1 = new bl(10); | ||
const expected = []; | ||
for (let i = 0; i < 25; i++) { | ||
bl$1.set(0, i + 1); | ||
assert.strictEqual(bl$1.get(0), i + 1); | ||
bl$1.increment(1); | ||
expected.push(i + 1); | ||
} | ||
assert.deepEqual([...bl$1.toBytes()], expected); | ||
}); | ||
it('sets bits, bulk incremented', () => { | ||
const bl$1 = new bl(10); | ||
const expected = []; | ||
for (let i = 0; i < 25; i++) { | ||
bl$1.set(i, i + 1); | ||
assert.strictEqual(bl$1.get(i), i + 1); | ||
expected.push(i + 1); | ||
} | ||
assert.deepEqual([...bl$1.toBytes()], []); | ||
for (let i = 0; i < 5; i++) { | ||
assert.strictEqual(bl$1.get(i), expected[i]); | ||
} | ||
bl$1.increment(5); | ||
assert.deepEqual([...bl$1.toBytes()].slice(0, 5), expected.slice(0, 5)); | ||
bl$1.increment(20); | ||
assert.deepEqual([...bl$1.toBytes()], expected); | ||
}); | ||
it('sets bits, partial progressive increment', () => { | ||
const bl$1 = new bl(10); | ||
const expected = []; | ||
for (let i = 0; i < 25; i++) { | ||
bl$1.set(i % 5, i + 1); | ||
assert.strictEqual(bl$1.get(i % 5), i + 1); | ||
expected.push(i + 1); | ||
if (i % 5 === 4) { | ||
bl$1.increment(5); | ||
describe('push', () => { | ||
it('push bits', () => { | ||
const bl$1 = new bl(10); | ||
const expected = []; | ||
for (let i = 0; i < 25; i++) { | ||
bl$1.push([i + 1]); | ||
expected.push(i + 1); | ||
} | ||
assert.deepEqual([...bl$1.toBytes()], expected); | ||
}); | ||
for (let i = 4; i < 21; i++) { | ||
it(`push Bl(${ i })`, () => { | ||
const bl$1 = new bl(i); | ||
const expected = [ | ||
1, | ||
2, | ||
3, | ||
4, | ||
5, | ||
6, | ||
7, | ||
8, | ||
9, | ||
10, | ||
100, | ||
110, | ||
120, | ||
11, | ||
12, | ||
130, | ||
13, | ||
14, | ||
15, | ||
16, | ||
17, | ||
18, | ||
19, | ||
20, | ||
21, | ||
22, | ||
23 | ||
]; | ||
for (let i = 0; i < 5; i++) { | ||
bl$1.push([i + 1]); | ||
} | ||
bl$1.push(Uint8Array.from([ | ||
6, | ||
7, | ||
8, | ||
9, | ||
10 | ||
])); | ||
bl$1.push([100]); | ||
bl$1.push(Uint8Array.from([ | ||
110, | ||
120 | ||
])); | ||
bl$1.push(Uint8Array.from([ | ||
11, | ||
12 | ||
])); | ||
bl$1.push([130]); | ||
bl$1.push(Uint8Array.from([ | ||
13, | ||
14, | ||
15, | ||
16, | ||
17, | ||
18, | ||
19, | ||
20, | ||
21, | ||
22, | ||
23 | ||
])); | ||
assert.deepEqual([...bl$1.toBytes()], expected); | ||
}); | ||
} | ||
assert.deepEqual([...bl$1.toBytes()], expected); | ||
}); | ||
it('copyTo, easy path', () => { | ||
const bl$1 = new bl(20); | ||
const expected = [ | ||
1, | ||
2, | ||
3, | ||
4, | ||
5, | ||
6, | ||
100, | ||
110, | ||
120, | ||
10, | ||
11, | ||
12, | ||
13 | ||
]; | ||
for (let i = 0; i < 5; i++) { | ||
bl$1.set(0, i + 1); | ||
assert.strictEqual(bl$1.get(0), i + 1); | ||
bl$1.increment(1); | ||
} | ||
bl$1.copyTo(0, Uint8Array.from([ | ||
6, | ||
7, | ||
8, | ||
9, | ||
10 | ||
])); | ||
bl$1.set(1, 100); | ||
bl$1.copyTo(2, Uint8Array.from([ | ||
110, | ||
120 | ||
])); | ||
for (let i = 0; i < 5; i++) { | ||
assert.strictEqual(bl$1.get(i), expected[i + 5]); | ||
} | ||
bl$1.increment(5); | ||
bl$1.copyTo(0, Uint8Array.from([ | ||
11, | ||
12 | ||
])); | ||
assert.strictEqual(bl$1.get(0), expected[10]); | ||
assert.strictEqual(bl$1.get(1), expected[11]); | ||
bl$1.increment(2); | ||
bl$1.set(0, 13); | ||
assert.strictEqual(bl$1.get(0), 13); | ||
bl$1.increment(1); | ||
assert.deepEqual([...bl$1.toBytes()], expected); | ||
}); | ||
it('copyTo, splice', () => { | ||
const bl$1 = new bl(4); | ||
const expected = [ | ||
1, | ||
2, | ||
3, | ||
4, | ||
5, | ||
6, | ||
100, | ||
110, | ||
120, | ||
10, | ||
11, | ||
12, | ||
13 | ||
]; | ||
for (let i = 0; i < 5; i++) { | ||
bl$1.set(0, i + 1); | ||
assert.strictEqual(bl$1.get(0), i + 1); | ||
bl$1.increment(1); | ||
} | ||
bl$1.copyTo(0, Uint8Array.from([ | ||
6, | ||
7, | ||
8, | ||
9, | ||
10 | ||
])); | ||
bl$1.set(1, 100); | ||
bl$1.copyTo(2, Uint8Array.from([ | ||
110, | ||
120 | ||
])); | ||
for (let i = 0; i < 5; i++) { | ||
assert.strictEqual(bl$1.get(i), expected[i + 5]); | ||
} | ||
bl$1.increment(5); | ||
bl$1.copyTo(0, Uint8Array.from([ | ||
11, | ||
12 | ||
])); | ||
assert.strictEqual(bl$1.get(0), expected[10]); | ||
assert.strictEqual(bl$1.get(1), expected[11]); | ||
bl$1.increment(2); | ||
bl$1.set(0, 13); | ||
assert.strictEqual(bl$1.get(0), 13); | ||
bl$1.increment(1); | ||
assert.deepEqual([...bl$1.toBytes()], expected); | ||
}); | ||
it('copyTo, insert', () => { | ||
const bl$1 = new bl(4); | ||
const expected = [ | ||
1, | ||
2, | ||
3, | ||
4, | ||
5, | ||
6, | ||
100, | ||
110, | ||
120, | ||
10, | ||
11, | ||
12, | ||
13, | ||
14, | ||
15, | ||
16, | ||
17 | ||
]; | ||
for (let i = 0; i < 5; i++) { | ||
bl$1.set(0, i + 1); | ||
assert.strictEqual(bl$1.get(0), i + 1); | ||
bl$1.increment(1); | ||
} | ||
bl$1.copyTo(0, Uint8Array.from([ | ||
6, | ||
7, | ||
8, | ||
9, | ||
10 | ||
])); | ||
bl$1.set(1, 100); | ||
bl$1.copyTo(2, Uint8Array.from([ | ||
110, | ||
120 | ||
])); | ||
for (let i = 0; i < 5; i++) { | ||
assert.strictEqual(bl$1.get(i), expected[i + 5]); | ||
} | ||
bl$1.increment(5); | ||
bl$1.copyTo(0, Uint8Array.from([ | ||
11, | ||
12, | ||
13, | ||
14, | ||
15, | ||
16 | ||
])); | ||
for (let i = 0; i < 6; i++) { | ||
assert.strictEqual(bl$1.get(i), expected[i + 10]); | ||
} | ||
bl$1.increment(6); | ||
bl$1.set(0, 17); | ||
assert.strictEqual(bl$1.get(0), 17); | ||
bl$1.increment(1); | ||
assert.deepEqual([...bl$1.toBytes()], expected); | ||
}); | ||
}); |
@@ -68,27 +68,21 @@ 'use strict'; | ||
function encodeUint(buf, token) { | ||
return encodeUintValue(buf, token.value); | ||
return encodeUintValue(buf, 0, token.value); | ||
} | ||
function encodeUintValue(buf, uint) { | ||
function encodeUintValue(buf, major, uint) { | ||
if (uint < uintBoundaries[0]) { | ||
buf.set(0, uint); | ||
return 1; | ||
} | ||
if (uint < uintBoundaries[1]) { | ||
buf.copyTo(0, [ | ||
24, | ||
buf.push([major | uint]); | ||
} else if (uint < uintBoundaries[1]) { | ||
buf.push([ | ||
major | 24, | ||
uint | ||
]); | ||
return 2; | ||
} | ||
if (uint < uintBoundaries[2]) { | ||
buf.copyTo(0, [ | ||
25, | ||
} else if (uint < uintBoundaries[2]) { | ||
buf.push([ | ||
major | 25, | ||
uint >>> 8, | ||
uint & 255 | ||
]); | ||
return 3; | ||
} | ||
if (uint < uintBoundaries[3]) { | ||
buf.copyTo(0, [ | ||
26, | ||
} else if (uint < uintBoundaries[3]) { | ||
buf.push([ | ||
major | 26, | ||
uint >>> 24 & 255, | ||
@@ -99,36 +93,36 @@ uint >>> 16 & 255, | ||
]); | ||
return 5; | ||
} else { | ||
const buint = BigInt(uint); | ||
if (buint < uintBoundaries[4]) { | ||
const set = [ | ||
major | 27, | ||
0, | ||
0, | ||
0, | ||
0, | ||
0, | ||
0, | ||
0 | ||
]; | ||
let lo = Number(buint & BigInt(4294967295)); | ||
let hi = Number(buint >> BigInt(32) & BigInt(4294967295)); | ||
set[8] = lo & 255; | ||
lo = lo >> 8; | ||
set[7] = lo & 255; | ||
lo = lo >> 8; | ||
set[6] = lo & 255; | ||
lo = lo >> 8; | ||
set[5] = lo & 255; | ||
set[4] = hi & 255; | ||
hi = hi >> 8; | ||
set[3] = hi & 255; | ||
hi = hi >> 8; | ||
set[2] = hi & 255; | ||
hi = hi >> 8; | ||
set[1] = hi & 255; | ||
buf.push(set); | ||
} else { | ||
throw new Error(`${ common.decodeErrPrefix } encountered BigInt larger than allowable range`); | ||
} | ||
} | ||
const buint = BigInt(uint); | ||
if (buint < uintBoundaries[4]) { | ||
const set = [ | ||
27, | ||
0, | ||
0, | ||
0, | ||
0, | ||
0, | ||
0, | ||
0 | ||
]; | ||
let lo = Number(buint & BigInt(4294967295)); | ||
let hi = Number(buint >> BigInt(32) & BigInt(4294967295)); | ||
set[8] = lo & 255; | ||
lo = lo >> 8; | ||
set[7] = lo & 255; | ||
lo = lo >> 8; | ||
set[6] = lo & 255; | ||
lo = lo >> 8; | ||
set[5] = lo & 255; | ||
set[4] = hi & 255; | ||
hi = hi >> 8; | ||
set[3] = hi & 255; | ||
hi = hi >> 8; | ||
set[2] = hi & 255; | ||
hi = hi >> 8; | ||
set[1] = hi & 255; | ||
buf.copyTo(0, set); | ||
return 9; | ||
} | ||
throw new Error(`${ common.decodeErrPrefix } encountered BigInt larger than allowable range`); | ||
} | ||
@@ -135,0 +129,0 @@ encodeUint.encodedSize = function encodedSize(token) { |
@@ -36,5 +36,3 @@ 'use strict'; | ||
const unsigned = typeof negint === 'bigint' ? negint * neg1b - pos1b : negint * -1 - 1; | ||
const bytes = _0uint.encodeUintValue(buf, unsigned); | ||
buf.set(0, buf.get(0) | token.type.majorEncoded); | ||
return bytes; | ||
_0uint.encodeUintValue(buf, token.type.majorEncoded, unsigned); | ||
} | ||
@@ -41,0 +39,0 @@ encodeNegint.encodedSize = function encodedSize(token) { |
@@ -30,18 +30,12 @@ 'use strict'; | ||
} | ||
function tokenBytes(token) { | ||
if (token.encodedBytes === undefined) { | ||
if (typeof token.value === 'string') { | ||
token.encodedBytes = byteUtils.fromString(token.value); | ||
return token.encodedBytes; | ||
} | ||
return token.value; | ||
function tokenBytes(token$1) { | ||
if (token$1.encodedBytes === undefined) { | ||
token$1.encodedBytes = token$1.type === token.Type.string ? byteUtils.fromString(token$1.value) : token$1.value; | ||
} | ||
return token.encodedBytes; | ||
return token$1.encodedBytes; | ||
} | ||
function encodeBytes(buf, token) { | ||
const bytes = tokenBytes(token); | ||
const prefixBytes = _0uint.encodeUintValue(buf, bytes.length); | ||
buf.set(0, buf.get(0) | token.type.majorEncoded); | ||
buf.copyTo(prefixBytes, bytes); | ||
return prefixBytes + bytes.length; | ||
_0uint.encodeUintValue(buf, token.type.majorEncoded, bytes.length); | ||
buf.push(bytes); | ||
} | ||
@@ -53,12 +47,6 @@ encodeBytes.encodedSize = function encodedSize(token) { | ||
encodeBytes.compareTokens = function compareTokens(tok1, tok2) { | ||
return compareBytes(tok1.value, tok2.value); | ||
return compareBytes(tokenBytes(tok1), tokenBytes(tok2)); | ||
}; | ||
function compareBytes(b1, b2) { | ||
if (b1.length < b2.length) { | ||
return -1; | ||
} | ||
if (b1.length > b2.length) { | ||
return 1; | ||
} | ||
return byteUtils.compare(b1, b2); | ||
return b1.length < b2.length ? -1 : b1.length > b2.length ? 1 : byteUtils.compare(b1, b2); | ||
} | ||
@@ -65,0 +53,0 @@ |
@@ -12,5 +12,5 @@ 'use strict'; | ||
function toToken(data, pos, prefix, length) { | ||
common.assertEnoughData(data, pos, prefix + length); | ||
const str = byteUtils.toString(data.subarray(pos + prefix, pos + prefix + length)); | ||
return new token.Token(token.Type.string, str, prefix + length); | ||
const totLength = prefix + length; | ||
common.assertEnoughData(data, pos, totLength); | ||
return new token.Token(token.Type.string, byteUtils.toString(data, pos + prefix, pos + totLength), totLength); | ||
} | ||
@@ -32,12 +32,3 @@ function decodeStringCompact(data, pos, minor, options) { | ||
} | ||
const encodeString = (buf, token) => _2bytes.encodeBytes(buf, token); | ||
encodeString.compareTokens = function compareTokens(tok1, tok2) { | ||
if (tok1.encodedBytes === undefined) { | ||
tok1.encodedBytes = byteUtils.fromString(tok1.value); | ||
} | ||
if (tok2.encodedBytes === undefined) { | ||
tok2.encodedBytes = byteUtils.fromString(tok2.value); | ||
} | ||
return _2bytes.compareBytes(tok1.encodedBytes, tok2.encodedBytes); | ||
}; | ||
const encodeString = _2bytes.encodeBytes; | ||
@@ -44,0 +35,0 @@ exports.decodeString16 = decodeString16; |
@@ -34,5 +34,3 @@ 'use strict'; | ||
function encodeArray(buf, token$1) { | ||
const prefixBytes = _0uint.encodeUintValue(buf, token$1.value); | ||
buf.set(0, buf.get(0) | token.Type.array.majorEncoded); | ||
return prefixBytes; | ||
_0uint.encodeUintValue(buf, token.Type.array.majorEncoded, token$1.value); | ||
} | ||
@@ -39,0 +37,0 @@ encodeArray.compareTokens = _0uint.encodeUint.compareTokens; |
@@ -34,5 +34,3 @@ 'use strict'; | ||
function encodeMap(buf, token$1) { | ||
const prefixBytes = _0uint.encodeUintValue(buf, token$1.value); | ||
buf.set(0, buf.get(0) | token.Type.map.majorEncoded); | ||
return prefixBytes; | ||
_0uint.encodeUintValue(buf, token.Type.map.majorEncoded, token$1.value); | ||
} | ||
@@ -39,0 +37,0 @@ encodeMap.compareTokens = _0uint.encodeUint.compareTokens; |
@@ -24,5 +24,3 @@ 'use strict'; | ||
function encodeTag(buf, token$1) { | ||
const prefixBytes = _0uint.encodeUintValue(buf, token$1.value); | ||
buf.set(0, buf.get(0) | token.Type.tag.majorEncoded); | ||
return prefixBytes; | ||
_0uint.encodeUintValue(buf, token.Type.tag.majorEncoded, token$1.value); | ||
} | ||
@@ -29,0 +27,0 @@ encodeTag.compareTokens = _0uint.encodeUint.compareTokens; |
@@ -47,39 +47,36 @@ 'use strict'; | ||
if (float === false) { | ||
buf.set(0, token.Type.float.majorEncoded | MINOR_FALSE); | ||
return 1; | ||
} | ||
if (float === true) { | ||
buf.set(0, token.Type.float.majorEncoded | MINOR_TRUE); | ||
return 1; | ||
} | ||
if (float === null) { | ||
buf.set(0, token.Type.float.majorEncoded | MINOR_NULL); | ||
return 1; | ||
} | ||
if (float === undefined) { | ||
buf.set(0, token.Type.float.majorEncoded | MINOR_UNDEFINED); | ||
return 1; | ||
} | ||
let decoded; | ||
if (!options || options.float64 !== true) { | ||
encodeFloat16(float); | ||
decoded = readFloat16(ui8a, 1); | ||
if (float === decoded || Number.isNaN(float)) { | ||
ui8a[0] = 249; | ||
buf.copyTo(0, ui8a.slice(0, 3)); | ||
return 3; | ||
buf.push([token.Type.float.majorEncoded | MINOR_FALSE]); | ||
} else if (float === true) { | ||
buf.push([token.Type.float.majorEncoded | MINOR_TRUE]); | ||
} else if (float === null) { | ||
buf.push([token.Type.float.majorEncoded | MINOR_NULL]); | ||
} else if (float === undefined) { | ||
buf.push([token.Type.float.majorEncoded | MINOR_UNDEFINED]); | ||
} else { | ||
let decoded; | ||
let success = false; | ||
if (!options || options.float64 !== true) { | ||
encodeFloat16(float); | ||
decoded = readFloat16(ui8a, 1); | ||
if (float === decoded || Number.isNaN(float)) { | ||
ui8a[0] = 249; | ||
buf.push(ui8a.slice(0, 3)); | ||
success = true; | ||
} else { | ||
encodeFloat32(float); | ||
decoded = readFloat32(ui8a, 1); | ||
if (float === decoded) { | ||
ui8a[0] = 250; | ||
buf.push(ui8a.slice(0, 5)); | ||
success = true; | ||
} | ||
} | ||
} | ||
encodeFloat32(float); | ||
decoded = readFloat32(ui8a, 1); | ||
if (float === decoded) { | ||
ui8a[0] = 250; | ||
buf.copyTo(0, ui8a.slice(0, 5)); | ||
return 5; | ||
if (!success) { | ||
encodeFloat64(float); | ||
decoded = readFloat64(ui8a, 1); | ||
ui8a[0] = 251; | ||
buf.push(ui8a.slice(0, 9)); | ||
} | ||
} | ||
encodeFloat64(float); | ||
decoded = readFloat64(ui8a, 1); | ||
ui8a[0] = 251; | ||
buf.copyTo(0, ui8a.slice(0, 9)); | ||
return 9; | ||
} | ||
@@ -86,0 +83,0 @@ encodeFloat.encodedSize = function encodedSize(token, options) { |
@@ -5,3 +5,3 @@ 'use strict'; | ||
const defaultChunkSize = 1024; | ||
const defaultChunkSize = 256; | ||
class Bl { | ||
@@ -24,74 +24,41 @@ constructor(chunkSize = defaultChunkSize) { | ||
} | ||
_growToPos(offset) { | ||
const pos = this.cursor + offset; | ||
while (pos > this.maxCursor) { | ||
const allocd = byteUtils.alloc(this.chunkSize); | ||
this.chunks.push(allocd); | ||
this.maxCursor += allocd.length; | ||
if (this._initReuseChunk === null) { | ||
this._initReuseChunk = allocd; | ||
push(bytes) { | ||
let topChunk = this.chunks[this.chunks.length - 1]; | ||
const newMax = this.cursor + bytes.length; | ||
if (newMax <= this.maxCursor + 1) { | ||
const chunkPos = topChunk.length - (this.maxCursor - this.cursor) - 1; | ||
topChunk.set(bytes, chunkPos); | ||
} else { | ||
if (topChunk) { | ||
const chunkPos = topChunk.length - (this.maxCursor - this.cursor) - 1; | ||
if (chunkPos < topChunk.length) { | ||
this.chunks[this.chunks.length - 1] = topChunk.subarray(0, chunkPos); | ||
this.maxCursor = this.cursor - 1; | ||
} | ||
} | ||
} | ||
return pos; | ||
} | ||
set(offset, byte) { | ||
const pos = this._growToPos(offset); | ||
let mc = this.maxCursor + 1; | ||
for (let i = this.chunks.length - 1; i >= 0; i--) { | ||
mc -= this.chunks[i].length; | ||
if (mc <= pos) { | ||
this.chunks[i][pos - mc] = byte; | ||
return; | ||
} | ||
} | ||
throw new Error('Unexpected internal error'); | ||
} | ||
get(offset) { | ||
const pos = this._growToPos(offset); | ||
let mc = this.maxCursor + 1; | ||
for (let i = this.chunks.length - 1; i >= 0; i--) { | ||
mc -= this.chunks[i].length; | ||
if (mc <= pos) { | ||
return this.chunks[i][pos - mc]; | ||
} | ||
} | ||
throw new Error('Unexpected internal error'); | ||
} | ||
copyTo(offset, bytes) { | ||
const pos = this._growToPos(offset); | ||
let mc = this.maxCursor + 1; | ||
for (let i = this.chunks.length - 1; i >= 0; i--) { | ||
mc -= this.chunks[i].length; | ||
if (mc <= pos) { | ||
const locPos = pos - mc; | ||
if (this.chunks[i].length - locPos >= bytes.length) { | ||
this.chunks[i].set(bytes, locPos); | ||
return; | ||
} else { | ||
if (locPos === 0) { | ||
this.chunks.splice(i, 0, bytes); | ||
} else { | ||
const after = this.chunks[i].subarray(locPos); | ||
this.chunks[i] = this.chunks[i].subarray(0, locPos); | ||
this.chunks.splice(i + 1, 0, bytes, after); | ||
} | ||
this.maxCursor += bytes.length; | ||
return; | ||
if (bytes.length < 64 && bytes.length < this.chunkSize) { | ||
topChunk = byteUtils.alloc(this.chunkSize); | ||
this.chunks.push(topChunk); | ||
this.maxCursor += topChunk.length; | ||
if (this._initReuseChunk === null) { | ||
this._initReuseChunk = topChunk; | ||
} | ||
topChunk.set(bytes, 0); | ||
} else { | ||
this.chunks.push(bytes); | ||
this.maxCursor += bytes.length; | ||
} | ||
} | ||
throw new Error('Unexpected internal error'); | ||
this.cursor += bytes.length; | ||
} | ||
increment(count) { | ||
this.cursor += count; | ||
} | ||
toBytes(reset = false) { | ||
let byts; | ||
if (this.chunks.length === 1) { | ||
if (reset && this.cursor > this.chunks[0].length / 2) { | ||
byts = this.chunks[0].subarray(0, this.cursor); | ||
const chunk = this.chunks[0]; | ||
if (reset && this.cursor > chunk.length / 2) { | ||
byts = this.cursor === chunk.length ? chunk : chunk.subarray(0, this.cursor); | ||
this._initReuseChunk = null; | ||
this.chunks = []; | ||
} else { | ||
byts = byteUtils.slice(this.chunks[0], 0, this.cursor); | ||
byts = byteUtils.slice(chunk, 0, this.cursor); | ||
} | ||
@@ -98,0 +65,0 @@ } else { |
@@ -12,13 +12,16 @@ 'use strict'; | ||
function asU8A(buf) { | ||
if (!(buf instanceof Uint8Array)) { | ||
return Uint8Array.from(buf); | ||
} | ||
return isBuffer(buf) ? new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength) : buf; | ||
} | ||
const toString = useBuffer ? bytes => { | ||
return global.Buffer.from(bytes).toString('utf8'); | ||
} : bytes => { | ||
return textDecoder.decode(bytes); | ||
const toString = useBuffer ? (bytes, start, end) => { | ||
return end - start > 64 ? global.Buffer.from(bytes.subarray(start, end)).toString('utf8') : utf8Slice(bytes, start, end); | ||
} : (bytes, start, end) => { | ||
return end - start > 64 ? textDecoder.decode(bytes.subarray(start, end)) : utf8Slice(bytes, start, end); | ||
}; | ||
const fromString = useBuffer ? string => { | ||
return global.Buffer.from(string); | ||
return string.length > 64 ? global.Buffer.from(string) : utf8ToBytes(string); | ||
} : string => { | ||
return textEncoder.encode(string); | ||
return string.length > 64 ? textEncoder.encode(string) : utf8ToBytes(string); | ||
}; | ||
@@ -37,3 +40,3 @@ const fromArray = arr => { | ||
const concat = useBuffer ? (chunks, length) => { | ||
chunks = chunks.map(c => global.Buffer.isBuffer(c) ? c : global.Buffer.from(c)); | ||
chunks = chunks.map(c => c instanceof Uint8Array ? c : global.Buffer.from(c)); | ||
return asU8A(global.Buffer.concat(chunks, length)); | ||
@@ -106,2 +109,128 @@ } : (chunks, length) => { | ||
} | ||
function utf8ToBytes(string, units = Infinity) { | ||
let codePoint; | ||
const length = string.length; | ||
let leadSurrogate = null; | ||
const bytes = []; | ||
for (let i = 0; i < length; ++i) { | ||
codePoint = string.charCodeAt(i); | ||
if (codePoint > 55295 && codePoint < 57344) { | ||
if (!leadSurrogate) { | ||
if (codePoint > 56319) { | ||
if ((units -= 3) > -1) | ||
bytes.push(239, 191, 189); | ||
continue; | ||
} else if (i + 1 === length) { | ||
if ((units -= 3) > -1) | ||
bytes.push(239, 191, 189); | ||
continue; | ||
} | ||
leadSurrogate = codePoint; | ||
continue; | ||
} | ||
if (codePoint < 56320) { | ||
if ((units -= 3) > -1) | ||
bytes.push(239, 191, 189); | ||
leadSurrogate = codePoint; | ||
continue; | ||
} | ||
codePoint = (leadSurrogate - 55296 << 10 | codePoint - 56320) + 65536; | ||
} else if (leadSurrogate) { | ||
if ((units -= 3) > -1) | ||
bytes.push(239, 191, 189); | ||
} | ||
leadSurrogate = null; | ||
if (codePoint < 128) { | ||
if ((units -= 1) < 0) | ||
break; | ||
bytes.push(codePoint); | ||
} else if (codePoint < 2048) { | ||
if ((units -= 2) < 0) | ||
break; | ||
bytes.push(codePoint >> 6 | 192, codePoint & 63 | 128); | ||
} else if (codePoint < 65536) { | ||
if ((units -= 3) < 0) | ||
break; | ||
bytes.push(codePoint >> 12 | 224, codePoint >> 6 & 63 | 128, codePoint & 63 | 128); | ||
} else if (codePoint < 1114112) { | ||
if ((units -= 4) < 0) | ||
break; | ||
bytes.push(codePoint >> 18 | 240, codePoint >> 12 & 63 | 128, codePoint >> 6 & 63 | 128, codePoint & 63 | 128); | ||
} else { | ||
throw new Error('Invalid code point'); | ||
} | ||
} | ||
return bytes; | ||
} | ||
function utf8Slice(buf, offset, end) { | ||
const res = []; | ||
while (offset < end) { | ||
const firstByte = buf[offset]; | ||
let codePoint = null; | ||
let bytesPerSequence = firstByte > 239 ? 4 : firstByte > 223 ? 3 : firstByte > 191 ? 2 : 1; | ||
if (offset + bytesPerSequence <= end) { | ||
let secondByte, thirdByte, fourthByte, tempCodePoint; | ||
switch (bytesPerSequence) { | ||
case 1: | ||
if (firstByte < 128) { | ||
codePoint = firstByte; | ||
} | ||
break; | ||
case 2: | ||
secondByte = buf[offset + 1]; | ||
if ((secondByte & 192) === 128) { | ||
tempCodePoint = (firstByte & 31) << 6 | secondByte & 63; | ||
if (tempCodePoint > 127) { | ||
codePoint = tempCodePoint; | ||
} | ||
} | ||
break; | ||
case 3: | ||
secondByte = buf[offset + 1]; | ||
thirdByte = buf[offset + 2]; | ||
if ((secondByte & 192) === 128 && (thirdByte & 192) === 128) { | ||
tempCodePoint = (firstByte & 15) << 12 | (secondByte & 63) << 6 | thirdByte & 63; | ||
if (tempCodePoint > 2047 && (tempCodePoint < 55296 || tempCodePoint > 57343)) { | ||
codePoint = tempCodePoint; | ||
} | ||
} | ||
break; | ||
case 4: | ||
secondByte = buf[offset + 1]; | ||
thirdByte = buf[offset + 2]; | ||
fourthByte = buf[offset + 3]; | ||
if ((secondByte & 192) === 128 && (thirdByte & 192) === 128 && (fourthByte & 192) === 128) { | ||
tempCodePoint = (firstByte & 15) << 18 | (secondByte & 63) << 12 | (thirdByte & 63) << 6 | fourthByte & 63; | ||
if (tempCodePoint > 65535 && tempCodePoint < 1114112) { | ||
codePoint = tempCodePoint; | ||
} | ||
} | ||
} | ||
} | ||
if (codePoint === null) { | ||
codePoint = 65533; | ||
bytesPerSequence = 1; | ||
} else if (codePoint > 65535) { | ||
codePoint -= 65536; | ||
res.push(codePoint >>> 10 & 1023 | 55296); | ||
codePoint = 56320 | codePoint & 1023; | ||
} | ||
res.push(codePoint); | ||
offset += bytesPerSequence; | ||
} | ||
return decodeCodePointsArray(res); | ||
} | ||
const MAX_ARGUMENTS_LENGTH = 4096; | ||
function decodeCodePointsArray(codePoints) { | ||
const len = codePoints.length; | ||
if (len <= MAX_ARGUMENTS_LENGTH) { | ||
return String.fromCharCode.apply(String, codePoints); | ||
} | ||
let res = ''; | ||
let i = 0; | ||
while (i < len) { | ||
res += String.fromCharCode.apply(String, codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH)); | ||
} | ||
return res; | ||
} | ||
@@ -108,0 +237,0 @@ exports.alloc = alloc; |
@@ -27,3 +27,3 @@ 'use strict'; | ||
let token = jump.quick[byt]; | ||
if (!token) { | ||
if (token === undefined) { | ||
const decoder = jump.jump[byt]; | ||
@@ -30,0 +30,0 @@ if (!decoder) { |
@@ -103,11 +103,16 @@ 'use strict'; | ||
refStack = Ref.createCheck(refStack, obj); | ||
const ret = [new token.Token(token.Type.array, obj.length)]; | ||
for (let i = 0; i < obj.length; i++) { | ||
ret[i + 1] = objectToTokens(obj[i], options, refStack); | ||
const entries = []; | ||
let i = 0; | ||
for (const e of obj) { | ||
entries[i++] = objectToTokens(e, options, refStack); | ||
} | ||
return ret; | ||
return [ | ||
new token.Token(token.Type.array, obj.length), | ||
entries | ||
]; | ||
}, | ||
Object(obj, typ, options, refStack) { | ||
const entriesIter = typ === 'Object' ? Object.entries(obj) : obj.entries(); | ||
const length = typ === 'Object' ? entriesIter.length : obj.size; | ||
const isMap = typ !== 'Object'; | ||
const keys = isMap ? obj.keys() : Object.keys(obj); | ||
const length = isMap ? obj.size : keys.length; | ||
if (!length) { | ||
@@ -119,11 +124,13 @@ return simpleTokens.emptyMap; | ||
let i = 0; | ||
for (const [key, value] of entriesIter) { | ||
for (const key of keys) { | ||
entries[i++] = [ | ||
objectToTokens(key, options, refStack), | ||
objectToTokens(value, options, refStack) | ||
objectToTokens(isMap ? obj.get(key) : obj[key], options, refStack) | ||
]; | ||
} | ||
sortMapEntries(entries); | ||
entries.unshift(new token.Token(token.Type.map, length)); | ||
return entries; | ||
entries.sort(mapSorter); | ||
return [ | ||
new token.Token(token.Type.map, length), | ||
entries | ||
]; | ||
} | ||
@@ -151,11 +158,7 @@ }; | ||
} | ||
function sortMapEntries(entries) { | ||
entries.sort(mapSorter); | ||
} | ||
function mapSorter(e1, e2) { | ||
const keyToken1 = Array.isArray(e1[0]) ? e1[0][0] : e1[0]; | ||
const keyToken2 = Array.isArray(e2[0]) ? e2[0][0] : e2[0]; | ||
const mcmp = keyToken1.type.compare(keyToken2.type); | ||
if (mcmp !== 0) { | ||
return mcmp; | ||
if (keyToken1.type !== keyToken2.type) { | ||
return keyToken1.type.compare(keyToken2.type); | ||
} | ||
@@ -170,16 +173,9 @@ const major = keyToken1.type.major; | ||
function tokensToEncoded(buf, tokens, options) { | ||
const it = tokens => { | ||
if (Array.isArray(tokens)) { | ||
for (const token of tokens) { | ||
enc(token); | ||
tokensToEncoded(buf, token, options); | ||
} | ||
}; | ||
const enc = token => { | ||
if (Array.isArray(token)) { | ||
it(token); | ||
} else { | ||
const length = encoders[token.type.major](buf, token, options); | ||
buf.increment(length); | ||
} | ||
}; | ||
enc(tokens); | ||
} else { | ||
encoders[tokens.type.major](buf, tokens, options); | ||
} | ||
} | ||
@@ -198,6 +194,3 @@ function encode(data, options) { | ||
const buf = new bl(size); | ||
const encodedSize = encoder(buf, tokens, options); | ||
if (encodedSize !== size) { | ||
throw new Error(`Unexpected error: pre-calculated length for ${ tokens } was wrong`); | ||
} | ||
encoder(buf, tokens, options); | ||
if (buf.chunks.length !== 1) { | ||
@@ -204,0 +197,0 @@ throw new Error(`Unexpected error: pre-calculated length for ${ tokens } was wrong`); |
@@ -12,202 +12,81 @@ 'use strict'; | ||
describe('Internal bytes list', () => { | ||
it('sets bits, individually incremented', () => { | ||
const bl$1 = new bl(10); | ||
const expected = []; | ||
for (let i = 0; i < 25; i++) { | ||
bl$1.set(0, i + 1); | ||
assert.strictEqual(bl$1.get(0), i + 1); | ||
bl$1.increment(1); | ||
expected.push(i + 1); | ||
} | ||
assert.deepEqual([...bl$1.toBytes()], expected); | ||
}); | ||
it('sets bits, bulk incremented', () => { | ||
const bl$1 = new bl(10); | ||
const expected = []; | ||
for (let i = 0; i < 25; i++) { | ||
bl$1.set(i, i + 1); | ||
assert.strictEqual(bl$1.get(i), i + 1); | ||
expected.push(i + 1); | ||
} | ||
assert.deepEqual([...bl$1.toBytes()], []); | ||
for (let i = 0; i < 5; i++) { | ||
assert.strictEqual(bl$1.get(i), expected[i]); | ||
} | ||
bl$1.increment(5); | ||
assert.deepEqual([...bl$1.toBytes()].slice(0, 5), expected.slice(0, 5)); | ||
bl$1.increment(20); | ||
assert.deepEqual([...bl$1.toBytes()], expected); | ||
}); | ||
it('sets bits, partial progressive increment', () => { | ||
const bl$1 = new bl(10); | ||
const expected = []; | ||
for (let i = 0; i < 25; i++) { | ||
bl$1.set(i % 5, i + 1); | ||
assert.strictEqual(bl$1.get(i % 5), i + 1); | ||
expected.push(i + 1); | ||
if (i % 5 === 4) { | ||
bl$1.increment(5); | ||
describe('push', () => { | ||
it('push bits', () => { | ||
const bl$1 = new bl(10); | ||
const expected = []; | ||
for (let i = 0; i < 25; i++) { | ||
bl$1.push([i + 1]); | ||
expected.push(i + 1); | ||
} | ||
assert.deepEqual([...bl$1.toBytes()], expected); | ||
}); | ||
for (let i = 4; i < 21; i++) { | ||
it(`push Bl(${ i })`, () => { | ||
const bl$1 = new bl(i); | ||
const expected = [ | ||
1, | ||
2, | ||
3, | ||
4, | ||
5, | ||
6, | ||
7, | ||
8, | ||
9, | ||
10, | ||
100, | ||
110, | ||
120, | ||
11, | ||
12, | ||
130, | ||
13, | ||
14, | ||
15, | ||
16, | ||
17, | ||
18, | ||
19, | ||
20, | ||
21, | ||
22, | ||
23 | ||
]; | ||
for (let i = 0; i < 5; i++) { | ||
bl$1.push([i + 1]); | ||
} | ||
bl$1.push(Uint8Array.from([ | ||
6, | ||
7, | ||
8, | ||
9, | ||
10 | ||
])); | ||
bl$1.push([100]); | ||
bl$1.push(Uint8Array.from([ | ||
110, | ||
120 | ||
])); | ||
bl$1.push(Uint8Array.from([ | ||
11, | ||
12 | ||
])); | ||
bl$1.push([130]); | ||
bl$1.push(Uint8Array.from([ | ||
13, | ||
14, | ||
15, | ||
16, | ||
17, | ||
18, | ||
19, | ||
20, | ||
21, | ||
22, | ||
23 | ||
])); | ||
assert.deepEqual([...bl$1.toBytes()], expected); | ||
}); | ||
} | ||
assert.deepEqual([...bl$1.toBytes()], expected); | ||
}); | ||
it('copyTo, easy path', () => { | ||
const bl$1 = new bl(20); | ||
const expected = [ | ||
1, | ||
2, | ||
3, | ||
4, | ||
5, | ||
6, | ||
100, | ||
110, | ||
120, | ||
10, | ||
11, | ||
12, | ||
13 | ||
]; | ||
for (let i = 0; i < 5; i++) { | ||
bl$1.set(0, i + 1); | ||
assert.strictEqual(bl$1.get(0), i + 1); | ||
bl$1.increment(1); | ||
} | ||
bl$1.copyTo(0, Uint8Array.from([ | ||
6, | ||
7, | ||
8, | ||
9, | ||
10 | ||
])); | ||
bl$1.set(1, 100); | ||
bl$1.copyTo(2, Uint8Array.from([ | ||
110, | ||
120 | ||
])); | ||
for (let i = 0; i < 5; i++) { | ||
assert.strictEqual(bl$1.get(i), expected[i + 5]); | ||
} | ||
bl$1.increment(5); | ||
bl$1.copyTo(0, Uint8Array.from([ | ||
11, | ||
12 | ||
])); | ||
assert.strictEqual(bl$1.get(0), expected[10]); | ||
assert.strictEqual(bl$1.get(1), expected[11]); | ||
bl$1.increment(2); | ||
bl$1.set(0, 13); | ||
assert.strictEqual(bl$1.get(0), 13); | ||
bl$1.increment(1); | ||
assert.deepEqual([...bl$1.toBytes()], expected); | ||
}); | ||
it('copyTo, splice', () => { | ||
const bl$1 = new bl(4); | ||
const expected = [ | ||
1, | ||
2, | ||
3, | ||
4, | ||
5, | ||
6, | ||
100, | ||
110, | ||
120, | ||
10, | ||
11, | ||
12, | ||
13 | ||
]; | ||
for (let i = 0; i < 5; i++) { | ||
bl$1.set(0, i + 1); | ||
assert.strictEqual(bl$1.get(0), i + 1); | ||
bl$1.increment(1); | ||
} | ||
bl$1.copyTo(0, Uint8Array.from([ | ||
6, | ||
7, | ||
8, | ||
9, | ||
10 | ||
])); | ||
bl$1.set(1, 100); | ||
bl$1.copyTo(2, Uint8Array.from([ | ||
110, | ||
120 | ||
])); | ||
for (let i = 0; i < 5; i++) { | ||
assert.strictEqual(bl$1.get(i), expected[i + 5]); | ||
} | ||
bl$1.increment(5); | ||
bl$1.copyTo(0, Uint8Array.from([ | ||
11, | ||
12 | ||
])); | ||
assert.strictEqual(bl$1.get(0), expected[10]); | ||
assert.strictEqual(bl$1.get(1), expected[11]); | ||
bl$1.increment(2); | ||
bl$1.set(0, 13); | ||
assert.strictEqual(bl$1.get(0), 13); | ||
bl$1.increment(1); | ||
assert.deepEqual([...bl$1.toBytes()], expected); | ||
}); | ||
it('copyTo, insert', () => { | ||
const bl$1 = new bl(4); | ||
const expected = [ | ||
1, | ||
2, | ||
3, | ||
4, | ||
5, | ||
6, | ||
100, | ||
110, | ||
120, | ||
10, | ||
11, | ||
12, | ||
13, | ||
14, | ||
15, | ||
16, | ||
17 | ||
]; | ||
for (let i = 0; i < 5; i++) { | ||
bl$1.set(0, i + 1); | ||
assert.strictEqual(bl$1.get(0), i + 1); | ||
bl$1.increment(1); | ||
} | ||
bl$1.copyTo(0, Uint8Array.from([ | ||
6, | ||
7, | ||
8, | ||
9, | ||
10 | ||
])); | ||
bl$1.set(1, 100); | ||
bl$1.copyTo(2, Uint8Array.from([ | ||
110, | ||
120 | ||
])); | ||
for (let i = 0; i < 5; i++) { | ||
assert.strictEqual(bl$1.get(i), expected[i + 5]); | ||
} | ||
bl$1.increment(5); | ||
bl$1.copyTo(0, Uint8Array.from([ | ||
11, | ||
12, | ||
13, | ||
14, | ||
15, | ||
16 | ||
])); | ||
for (let i = 0; i < 6; i++) { | ||
assert.strictEqual(bl$1.get(i), expected[i + 10]); | ||
} | ||
bl$1.increment(6); | ||
bl$1.set(0, 17); | ||
assert.strictEqual(bl$1.get(0), 17); | ||
bl$1.increment(1); | ||
assert.deepEqual([...bl$1.toBytes()], expected); | ||
}); | ||
}); |
@@ -5,202 +5,81 @@ import chai from 'chai'; | ||
describe('Internal bytes list', () => { | ||
it('sets bits, individually incremented', () => { | ||
const bl = new Bl(10); | ||
const expected = []; | ||
for (let i = 0; i < 25; i++) { | ||
bl.set(0, i + 1); | ||
assert.strictEqual(bl.get(0), i + 1); | ||
bl.increment(1); | ||
expected.push(i + 1); | ||
} | ||
assert.deepEqual([...bl.toBytes()], expected); | ||
}); | ||
it('sets bits, bulk incremented', () => { | ||
const bl = new Bl(10); | ||
const expected = []; | ||
for (let i = 0; i < 25; i++) { | ||
bl.set(i, i + 1); | ||
assert.strictEqual(bl.get(i), i + 1); | ||
expected.push(i + 1); | ||
} | ||
assert.deepEqual([...bl.toBytes()], []); | ||
for (let i = 0; i < 5; i++) { | ||
assert.strictEqual(bl.get(i), expected[i]); | ||
} | ||
bl.increment(5); | ||
assert.deepEqual([...bl.toBytes()].slice(0, 5), expected.slice(0, 5)); | ||
bl.increment(20); | ||
assert.deepEqual([...bl.toBytes()], expected); | ||
}); | ||
it('sets bits, partial progressive increment', () => { | ||
const bl = new Bl(10); | ||
const expected = []; | ||
for (let i = 0; i < 25; i++) { | ||
bl.set(i % 5, i + 1); | ||
assert.strictEqual(bl.get(i % 5), i + 1); | ||
expected.push(i + 1); | ||
if (i % 5 === 4) { | ||
bl.increment(5); | ||
describe('push', () => { | ||
it('push bits', () => { | ||
const bl = new Bl(10); | ||
const expected = []; | ||
for (let i = 0; i < 25; i++) { | ||
bl.push([i + 1]); | ||
expected.push(i + 1); | ||
} | ||
assert.deepEqual([...bl.toBytes()], expected); | ||
}); | ||
for (let i = 4; i < 21; i++) { | ||
it(`push Bl(${ i })`, () => { | ||
const bl = new Bl(i); | ||
const expected = [ | ||
1, | ||
2, | ||
3, | ||
4, | ||
5, | ||
6, | ||
7, | ||
8, | ||
9, | ||
10, | ||
100, | ||
110, | ||
120, | ||
11, | ||
12, | ||
130, | ||
13, | ||
14, | ||
15, | ||
16, | ||
17, | ||
18, | ||
19, | ||
20, | ||
21, | ||
22, | ||
23 | ||
]; | ||
for (let i = 0; i < 5; i++) { | ||
bl.push([i + 1]); | ||
} | ||
bl.push(Uint8Array.from([ | ||
6, | ||
7, | ||
8, | ||
9, | ||
10 | ||
])); | ||
bl.push([100]); | ||
bl.push(Uint8Array.from([ | ||
110, | ||
120 | ||
])); | ||
bl.push(Uint8Array.from([ | ||
11, | ||
12 | ||
])); | ||
bl.push([130]); | ||
bl.push(Uint8Array.from([ | ||
13, | ||
14, | ||
15, | ||
16, | ||
17, | ||
18, | ||
19, | ||
20, | ||
21, | ||
22, | ||
23 | ||
])); | ||
assert.deepEqual([...bl.toBytes()], expected); | ||
}); | ||
} | ||
assert.deepEqual([...bl.toBytes()], expected); | ||
}); | ||
it('copyTo, easy path', () => { | ||
const bl = new Bl(20); | ||
const expected = [ | ||
1, | ||
2, | ||
3, | ||
4, | ||
5, | ||
6, | ||
100, | ||
110, | ||
120, | ||
10, | ||
11, | ||
12, | ||
13 | ||
]; | ||
for (let i = 0; i < 5; i++) { | ||
bl.set(0, i + 1); | ||
assert.strictEqual(bl.get(0), i + 1); | ||
bl.increment(1); | ||
} | ||
bl.copyTo(0, Uint8Array.from([ | ||
6, | ||
7, | ||
8, | ||
9, | ||
10 | ||
])); | ||
bl.set(1, 100); | ||
bl.copyTo(2, Uint8Array.from([ | ||
110, | ||
120 | ||
])); | ||
for (let i = 0; i < 5; i++) { | ||
assert.strictEqual(bl.get(i), expected[i + 5]); | ||
} | ||
bl.increment(5); | ||
bl.copyTo(0, Uint8Array.from([ | ||
11, | ||
12 | ||
])); | ||
assert.strictEqual(bl.get(0), expected[10]); | ||
assert.strictEqual(bl.get(1), expected[11]); | ||
bl.increment(2); | ||
bl.set(0, 13); | ||
assert.strictEqual(bl.get(0), 13); | ||
bl.increment(1); | ||
assert.deepEqual([...bl.toBytes()], expected); | ||
}); | ||
it('copyTo, splice', () => { | ||
const bl = new Bl(4); | ||
const expected = [ | ||
1, | ||
2, | ||
3, | ||
4, | ||
5, | ||
6, | ||
100, | ||
110, | ||
120, | ||
10, | ||
11, | ||
12, | ||
13 | ||
]; | ||
for (let i = 0; i < 5; i++) { | ||
bl.set(0, i + 1); | ||
assert.strictEqual(bl.get(0), i + 1); | ||
bl.increment(1); | ||
} | ||
bl.copyTo(0, Uint8Array.from([ | ||
6, | ||
7, | ||
8, | ||
9, | ||
10 | ||
])); | ||
bl.set(1, 100); | ||
bl.copyTo(2, Uint8Array.from([ | ||
110, | ||
120 | ||
])); | ||
for (let i = 0; i < 5; i++) { | ||
assert.strictEqual(bl.get(i), expected[i + 5]); | ||
} | ||
bl.increment(5); | ||
bl.copyTo(0, Uint8Array.from([ | ||
11, | ||
12 | ||
])); | ||
assert.strictEqual(bl.get(0), expected[10]); | ||
assert.strictEqual(bl.get(1), expected[11]); | ||
bl.increment(2); | ||
bl.set(0, 13); | ||
assert.strictEqual(bl.get(0), 13); | ||
bl.increment(1); | ||
assert.deepEqual([...bl.toBytes()], expected); | ||
}); | ||
it('copyTo, insert', () => { | ||
const bl = new Bl(4); | ||
const expected = [ | ||
1, | ||
2, | ||
3, | ||
4, | ||
5, | ||
6, | ||
100, | ||
110, | ||
120, | ||
10, | ||
11, | ||
12, | ||
13, | ||
14, | ||
15, | ||
16, | ||
17 | ||
]; | ||
for (let i = 0; i < 5; i++) { | ||
bl.set(0, i + 1); | ||
assert.strictEqual(bl.get(0), i + 1); | ||
bl.increment(1); | ||
} | ||
bl.copyTo(0, Uint8Array.from([ | ||
6, | ||
7, | ||
8, | ||
9, | ||
10 | ||
])); | ||
bl.set(1, 100); | ||
bl.copyTo(2, Uint8Array.from([ | ||
110, | ||
120 | ||
])); | ||
for (let i = 0; i < 5; i++) { | ||
assert.strictEqual(bl.get(i), expected[i + 5]); | ||
} | ||
bl.increment(5); | ||
bl.copyTo(0, Uint8Array.from([ | ||
11, | ||
12, | ||
13, | ||
14, | ||
15, | ||
16 | ||
])); | ||
for (let i = 0; i < 6; i++) { | ||
assert.strictEqual(bl.get(i), expected[i + 10]); | ||
} | ||
bl.increment(6); | ||
bl.set(0, 17); | ||
assert.strictEqual(bl.get(0), 17); | ||
bl.increment(1); | ||
assert.deepEqual([...bl.toBytes()], expected); | ||
}); | ||
}); |
@@ -69,27 +69,21 @@ import { | ||
export function encodeUint(buf, token) { | ||
return encodeUintValue(buf, token.value); | ||
return encodeUintValue(buf, 0, token.value); | ||
} | ||
export function encodeUintValue(buf, uint) { | ||
export function encodeUintValue(buf, major, uint) { | ||
if (uint < uintBoundaries[0]) { | ||
buf.set(0, uint); | ||
return 1; | ||
} | ||
if (uint < uintBoundaries[1]) { | ||
buf.copyTo(0, [ | ||
24, | ||
buf.push([major | uint]); | ||
} else if (uint < uintBoundaries[1]) { | ||
buf.push([ | ||
major | 24, | ||
uint | ||
]); | ||
return 2; | ||
} | ||
if (uint < uintBoundaries[2]) { | ||
buf.copyTo(0, [ | ||
25, | ||
} else if (uint < uintBoundaries[2]) { | ||
buf.push([ | ||
major | 25, | ||
uint >>> 8, | ||
uint & 255 | ||
]); | ||
return 3; | ||
} | ||
if (uint < uintBoundaries[3]) { | ||
buf.copyTo(0, [ | ||
26, | ||
} else if (uint < uintBoundaries[3]) { | ||
buf.push([ | ||
major | 26, | ||
uint >>> 24 & 255, | ||
@@ -100,36 +94,36 @@ uint >>> 16 & 255, | ||
]); | ||
return 5; | ||
} else { | ||
const buint = BigInt(uint); | ||
if (buint < uintBoundaries[4]) { | ||
const set = [ | ||
major | 27, | ||
0, | ||
0, | ||
0, | ||
0, | ||
0, | ||
0, | ||
0 | ||
]; | ||
let lo = Number(buint & BigInt(4294967295)); | ||
let hi = Number(buint >> BigInt(32) & BigInt(4294967295)); | ||
set[8] = lo & 255; | ||
lo = lo >> 8; | ||
set[7] = lo & 255; | ||
lo = lo >> 8; | ||
set[6] = lo & 255; | ||
lo = lo >> 8; | ||
set[5] = lo & 255; | ||
set[4] = hi & 255; | ||
hi = hi >> 8; | ||
set[3] = hi & 255; | ||
hi = hi >> 8; | ||
set[2] = hi & 255; | ||
hi = hi >> 8; | ||
set[1] = hi & 255; | ||
buf.push(set); | ||
} else { | ||
throw new Error(`${ decodeErrPrefix } encountered BigInt larger than allowable range`); | ||
} | ||
} | ||
const buint = BigInt(uint); | ||
if (buint < uintBoundaries[4]) { | ||
const set = [ | ||
27, | ||
0, | ||
0, | ||
0, | ||
0, | ||
0, | ||
0, | ||
0 | ||
]; | ||
let lo = Number(buint & BigInt(4294967295)); | ||
let hi = Number(buint >> BigInt(32) & BigInt(4294967295)); | ||
set[8] = lo & 255; | ||
lo = lo >> 8; | ||
set[7] = lo & 255; | ||
lo = lo >> 8; | ||
set[6] = lo & 255; | ||
lo = lo >> 8; | ||
set[5] = lo & 255; | ||
set[4] = hi & 255; | ||
hi = hi >> 8; | ||
set[3] = hi & 255; | ||
hi = hi >> 8; | ||
set[2] = hi & 255; | ||
hi = hi >> 8; | ||
set[1] = hi & 255; | ||
buf.copyTo(0, set); | ||
return 9; | ||
} | ||
throw new Error(`${ decodeErrPrefix } encountered BigInt larger than allowable range`); | ||
} | ||
@@ -136,0 +130,0 @@ encodeUint.encodedSize = function encodedSize(token) { |
@@ -34,5 +34,3 @@ import { | ||
const unsigned = typeof negint === 'bigint' ? negint * neg1b - pos1b : negint * -1 - 1; | ||
const bytes = uint.encodeUintValue(buf, unsigned); | ||
buf.set(0, buf.get(0) | token.type.majorEncoded); | ||
return bytes; | ||
uint.encodeUintValue(buf, token.type.majorEncoded, unsigned); | ||
} | ||
@@ -39,0 +37,0 @@ encodeNegint.encodedSize = function encodedSize(token) { |
@@ -34,7 +34,3 @@ import { | ||
if (token.encodedBytes === undefined) { | ||
if (typeof token.value === 'string') { | ||
token.encodedBytes = fromString(token.value); | ||
return token.encodedBytes; | ||
} | ||
return token.value; | ||
token.encodedBytes = token.type === Type.string ? fromString(token.value) : token.value; | ||
} | ||
@@ -45,6 +41,4 @@ return token.encodedBytes; | ||
const bytes = tokenBytes(token); | ||
const prefixBytes = uint.encodeUintValue(buf, bytes.length); | ||
buf.set(0, buf.get(0) | token.type.majorEncoded); | ||
buf.copyTo(prefixBytes, bytes); | ||
return prefixBytes + bytes.length; | ||
uint.encodeUintValue(buf, token.type.majorEncoded, bytes.length); | ||
buf.push(bytes); | ||
} | ||
@@ -56,12 +50,6 @@ encodeBytes.encodedSize = function encodedSize(token) { | ||
encodeBytes.compareTokens = function compareTokens(tok1, tok2) { | ||
return compareBytes(tok1.value, tok2.value); | ||
return compareBytes(tokenBytes(tok1), tokenBytes(tok2)); | ||
}; | ||
export function compareBytes(b1, b2) { | ||
if (b1.length < b2.length) { | ||
return -1; | ||
} | ||
if (b1.length > b2.length) { | ||
return 1; | ||
} | ||
return compare(b1, b2); | ||
return b1.length < b2.length ? -1 : b1.length > b2.length ? 1 : compare(b1, b2); | ||
} |
@@ -7,14 +7,8 @@ import { | ||
import * as uint from './0uint.js'; | ||
import { | ||
encodeBytes, | ||
compareBytes | ||
} from './2bytes.js'; | ||
import { | ||
fromString, | ||
toString | ||
} from './byte-utils.js'; | ||
import { encodeBytes } from './2bytes.js'; | ||
import { toString } from './byte-utils.js'; | ||
function toToken(data, pos, prefix, length) { | ||
assertEnoughData(data, pos, prefix + length); | ||
const str = toString(data.subarray(pos + prefix, pos + prefix + length)); | ||
return new Token(Type.string, str, prefix + length); | ||
const totLength = prefix + length; | ||
assertEnoughData(data, pos, totLength); | ||
return new Token(Type.string, toString(data, pos + prefix, pos + totLength), totLength); | ||
} | ||
@@ -36,11 +30,2 @@ export function decodeStringCompact(data, pos, minor, options) { | ||
} | ||
export const encodeString = (buf, token) => encodeBytes(buf, token); | ||
encodeString.compareTokens = function compareTokens(tok1, tok2) { | ||
if (tok1.encodedBytes === undefined) { | ||
tok1.encodedBytes = fromString(tok1.value); | ||
} | ||
if (tok2.encodedBytes === undefined) { | ||
tok2.encodedBytes = fromString(tok2.value); | ||
} | ||
return compareBytes(tok1.encodedBytes, tok2.encodedBytes); | ||
}; | ||
export const encodeString = encodeBytes; |
@@ -32,6 +32,4 @@ import { | ||
export function encodeArray(buf, token) { | ||
const prefixBytes = uint.encodeUintValue(buf, token.value); | ||
buf.set(0, buf.get(0) | Type.array.majorEncoded); | ||
return prefixBytes; | ||
uint.encodeUintValue(buf, Type.array.majorEncoded, token.value); | ||
} | ||
encodeArray.compareTokens = uint.encodeUint.compareTokens; |
@@ -32,6 +32,4 @@ import { | ||
export function encodeMap(buf, token) { | ||
const prefixBytes = uint.encodeUintValue(buf, token.value); | ||
buf.set(0, buf.get(0) | Type.map.majorEncoded); | ||
return prefixBytes; | ||
uint.encodeUintValue(buf, Type.map.majorEncoded, token.value); | ||
} | ||
encodeMap.compareTokens = uint.encodeUint.compareTokens; |
@@ -22,6 +22,4 @@ import { | ||
export function encodeTag(buf, token) { | ||
const prefixBytes = uint.encodeUintValue(buf, token.value); | ||
buf.set(0, buf.get(0) | Type.tag.majorEncoded); | ||
return prefixBytes; | ||
uint.encodeUintValue(buf, Type.tag.majorEncoded, token.value); | ||
} | ||
encodeTag.compareTokens = uint.encodeUint.compareTokens; |
@@ -45,39 +45,36 @@ import { | ||
if (float === false) { | ||
buf.set(0, Type.float.majorEncoded | MINOR_FALSE); | ||
return 1; | ||
} | ||
if (float === true) { | ||
buf.set(0, Type.float.majorEncoded | MINOR_TRUE); | ||
return 1; | ||
} | ||
if (float === null) { | ||
buf.set(0, Type.float.majorEncoded | MINOR_NULL); | ||
return 1; | ||
} | ||
if (float === undefined) { | ||
buf.set(0, Type.float.majorEncoded | MINOR_UNDEFINED); | ||
return 1; | ||
} | ||
let decoded; | ||
if (!options || options.float64 !== true) { | ||
encodeFloat16(float); | ||
decoded = readFloat16(ui8a, 1); | ||
if (float === decoded || Number.isNaN(float)) { | ||
ui8a[0] = 249; | ||
buf.copyTo(0, ui8a.slice(0, 3)); | ||
return 3; | ||
buf.push([Type.float.majorEncoded | MINOR_FALSE]); | ||
} else if (float === true) { | ||
buf.push([Type.float.majorEncoded | MINOR_TRUE]); | ||
} else if (float === null) { | ||
buf.push([Type.float.majorEncoded | MINOR_NULL]); | ||
} else if (float === undefined) { | ||
buf.push([Type.float.majorEncoded | MINOR_UNDEFINED]); | ||
} else { | ||
let decoded; | ||
let success = false; | ||
if (!options || options.float64 !== true) { | ||
encodeFloat16(float); | ||
decoded = readFloat16(ui8a, 1); | ||
if (float === decoded || Number.isNaN(float)) { | ||
ui8a[0] = 249; | ||
buf.push(ui8a.slice(0, 3)); | ||
success = true; | ||
} else { | ||
encodeFloat32(float); | ||
decoded = readFloat32(ui8a, 1); | ||
if (float === decoded) { | ||
ui8a[0] = 250; | ||
buf.push(ui8a.slice(0, 5)); | ||
success = true; | ||
} | ||
} | ||
} | ||
encodeFloat32(float); | ||
decoded = readFloat32(ui8a, 1); | ||
if (float === decoded) { | ||
ui8a[0] = 250; | ||
buf.copyTo(0, ui8a.slice(0, 5)); | ||
return 5; | ||
if (!success) { | ||
encodeFloat64(float); | ||
decoded = readFloat64(ui8a, 1); | ||
ui8a[0] = 251; | ||
buf.push(ui8a.slice(0, 9)); | ||
} | ||
} | ||
encodeFloat64(float); | ||
decoded = readFloat64(ui8a, 1); | ||
ui8a[0] = 251; | ||
buf.copyTo(0, ui8a.slice(0, 9)); | ||
return 9; | ||
} | ||
@@ -84,0 +81,0 @@ encodeFloat.encodedSize = function encodedSize(token, options) { |
@@ -6,3 +6,3 @@ import { | ||
} from './byte-utils.js'; | ||
const defaultChunkSize = 1024; | ||
const defaultChunkSize = 256; | ||
class Bl { | ||
@@ -25,74 +25,41 @@ constructor(chunkSize = defaultChunkSize) { | ||
} | ||
_growToPos(offset) { | ||
const pos = this.cursor + offset; | ||
while (pos > this.maxCursor) { | ||
const allocd = alloc(this.chunkSize); | ||
this.chunks.push(allocd); | ||
this.maxCursor += allocd.length; | ||
if (this._initReuseChunk === null) { | ||
this._initReuseChunk = allocd; | ||
push(bytes) { | ||
let topChunk = this.chunks[this.chunks.length - 1]; | ||
const newMax = this.cursor + bytes.length; | ||
if (newMax <= this.maxCursor + 1) { | ||
const chunkPos = topChunk.length - (this.maxCursor - this.cursor) - 1; | ||
topChunk.set(bytes, chunkPos); | ||
} else { | ||
if (topChunk) { | ||
const chunkPos = topChunk.length - (this.maxCursor - this.cursor) - 1; | ||
if (chunkPos < topChunk.length) { | ||
this.chunks[this.chunks.length - 1] = topChunk.subarray(0, chunkPos); | ||
this.maxCursor = this.cursor - 1; | ||
} | ||
} | ||
} | ||
return pos; | ||
} | ||
set(offset, byte) { | ||
const pos = this._growToPos(offset); | ||
let mc = this.maxCursor + 1; | ||
for (let i = this.chunks.length - 1; i >= 0; i--) { | ||
mc -= this.chunks[i].length; | ||
if (mc <= pos) { | ||
this.chunks[i][pos - mc] = byte; | ||
return; | ||
} | ||
} | ||
throw new Error('Unexpected internal error'); | ||
} | ||
get(offset) { | ||
const pos = this._growToPos(offset); | ||
let mc = this.maxCursor + 1; | ||
for (let i = this.chunks.length - 1; i >= 0; i--) { | ||
mc -= this.chunks[i].length; | ||
if (mc <= pos) { | ||
return this.chunks[i][pos - mc]; | ||
} | ||
} | ||
throw new Error('Unexpected internal error'); | ||
} | ||
copyTo(offset, bytes) { | ||
const pos = this._growToPos(offset); | ||
let mc = this.maxCursor + 1; | ||
for (let i = this.chunks.length - 1; i >= 0; i--) { | ||
mc -= this.chunks[i].length; | ||
if (mc <= pos) { | ||
const locPos = pos - mc; | ||
if (this.chunks[i].length - locPos >= bytes.length) { | ||
this.chunks[i].set(bytes, locPos); | ||
return; | ||
} else { | ||
if (locPos === 0) { | ||
this.chunks.splice(i, 0, bytes); | ||
} else { | ||
const after = this.chunks[i].subarray(locPos); | ||
this.chunks[i] = this.chunks[i].subarray(0, locPos); | ||
this.chunks.splice(i + 1, 0, bytes, after); | ||
} | ||
this.maxCursor += bytes.length; | ||
return; | ||
if (bytes.length < 64 && bytes.length < this.chunkSize) { | ||
topChunk = alloc(this.chunkSize); | ||
this.chunks.push(topChunk); | ||
this.maxCursor += topChunk.length; | ||
if (this._initReuseChunk === null) { | ||
this._initReuseChunk = topChunk; | ||
} | ||
topChunk.set(bytes, 0); | ||
} else { | ||
this.chunks.push(bytes); | ||
this.maxCursor += bytes.length; | ||
} | ||
} | ||
throw new Error('Unexpected internal error'); | ||
this.cursor += bytes.length; | ||
} | ||
increment(count) { | ||
this.cursor += count; | ||
} | ||
toBytes(reset = false) { | ||
let byts; | ||
if (this.chunks.length === 1) { | ||
if (reset && this.cursor > this.chunks[0].length / 2) { | ||
byts = this.chunks[0].subarray(0, this.cursor); | ||
const chunk = this.chunks[0]; | ||
if (reset && this.cursor > chunk.length / 2) { | ||
byts = this.cursor === chunk.length ? chunk : chunk.subarray(0, this.cursor); | ||
this._initReuseChunk = null; | ||
this.chunks = []; | ||
} else { | ||
byts = slice(this.chunks[0], 0, this.cursor); | ||
byts = slice(chunk, 0, this.cursor); | ||
} | ||
@@ -99,0 +66,0 @@ } else { |
@@ -8,13 +8,16 @@ export const useBuffer = !process.browser && global.Buffer && typeof global.Buffer.isBuffer === 'function'; | ||
export function asU8A(buf) { | ||
if (!(buf instanceof Uint8Array)) { | ||
return Uint8Array.from(buf); | ||
} | ||
return isBuffer(buf) ? new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength) : buf; | ||
} | ||
export const toString = useBuffer ? bytes => { | ||
return global.Buffer.from(bytes).toString('utf8'); | ||
} : bytes => { | ||
return textDecoder.decode(bytes); | ||
export const toString = useBuffer ? (bytes, start, end) => { | ||
return end - start > 64 ? global.Buffer.from(bytes.subarray(start, end)).toString('utf8') : utf8Slice(bytes, start, end); | ||
} : (bytes, start, end) => { | ||
return end - start > 64 ? textDecoder.decode(bytes.subarray(start, end)) : utf8Slice(bytes, start, end); | ||
}; | ||
export const fromString = useBuffer ? string => { | ||
return global.Buffer.from(string); | ||
return string.length > 64 ? global.Buffer.from(string) : utf8ToBytes(string); | ||
} : string => { | ||
return textEncoder.encode(string); | ||
return string.length > 64 ? textEncoder.encode(string) : utf8ToBytes(string); | ||
}; | ||
@@ -33,3 +36,3 @@ export const fromArray = arr => { | ||
export const concat = useBuffer ? (chunks, length) => { | ||
chunks = chunks.map(c => global.Buffer.isBuffer(c) ? c : global.Buffer.from(c)); | ||
chunks = chunks.map(c => c instanceof Uint8Array ? c : global.Buffer.from(c)); | ||
return asU8A(global.Buffer.concat(chunks, length)); | ||
@@ -101,2 +104,128 @@ } : (chunks, length) => { | ||
return 0; | ||
} | ||
function utf8ToBytes(string, units = Infinity) { | ||
let codePoint; | ||
const length = string.length; | ||
let leadSurrogate = null; | ||
const bytes = []; | ||
for (let i = 0; i < length; ++i) { | ||
codePoint = string.charCodeAt(i); | ||
if (codePoint > 55295 && codePoint < 57344) { | ||
if (!leadSurrogate) { | ||
if (codePoint > 56319) { | ||
if ((units -= 3) > -1) | ||
bytes.push(239, 191, 189); | ||
continue; | ||
} else if (i + 1 === length) { | ||
if ((units -= 3) > -1) | ||
bytes.push(239, 191, 189); | ||
continue; | ||
} | ||
leadSurrogate = codePoint; | ||
continue; | ||
} | ||
if (codePoint < 56320) { | ||
if ((units -= 3) > -1) | ||
bytes.push(239, 191, 189); | ||
leadSurrogate = codePoint; | ||
continue; | ||
} | ||
codePoint = (leadSurrogate - 55296 << 10 | codePoint - 56320) + 65536; | ||
} else if (leadSurrogate) { | ||
if ((units -= 3) > -1) | ||
bytes.push(239, 191, 189); | ||
} | ||
leadSurrogate = null; | ||
if (codePoint < 128) { | ||
if ((units -= 1) < 0) | ||
break; | ||
bytes.push(codePoint); | ||
} else if (codePoint < 2048) { | ||
if ((units -= 2) < 0) | ||
break; | ||
bytes.push(codePoint >> 6 | 192, codePoint & 63 | 128); | ||
} else if (codePoint < 65536) { | ||
if ((units -= 3) < 0) | ||
break; | ||
bytes.push(codePoint >> 12 | 224, codePoint >> 6 & 63 | 128, codePoint & 63 | 128); | ||
} else if (codePoint < 1114112) { | ||
if ((units -= 4) < 0) | ||
break; | ||
bytes.push(codePoint >> 18 | 240, codePoint >> 12 & 63 | 128, codePoint >> 6 & 63 | 128, codePoint & 63 | 128); | ||
} else { | ||
throw new Error('Invalid code point'); | ||
} | ||
} | ||
return bytes; | ||
} | ||
function utf8Slice(buf, offset, end) { | ||
const res = []; | ||
while (offset < end) { | ||
const firstByte = buf[offset]; | ||
let codePoint = null; | ||
let bytesPerSequence = firstByte > 239 ? 4 : firstByte > 223 ? 3 : firstByte > 191 ? 2 : 1; | ||
if (offset + bytesPerSequence <= end) { | ||
let secondByte, thirdByte, fourthByte, tempCodePoint; | ||
switch (bytesPerSequence) { | ||
case 1: | ||
if (firstByte < 128) { | ||
codePoint = firstByte; | ||
} | ||
break; | ||
case 2: | ||
secondByte = buf[offset + 1]; | ||
if ((secondByte & 192) === 128) { | ||
tempCodePoint = (firstByte & 31) << 6 | secondByte & 63; | ||
if (tempCodePoint > 127) { | ||
codePoint = tempCodePoint; | ||
} | ||
} | ||
break; | ||
case 3: | ||
secondByte = buf[offset + 1]; | ||
thirdByte = buf[offset + 2]; | ||
if ((secondByte & 192) === 128 && (thirdByte & 192) === 128) { | ||
tempCodePoint = (firstByte & 15) << 12 | (secondByte & 63) << 6 | thirdByte & 63; | ||
if (tempCodePoint > 2047 && (tempCodePoint < 55296 || tempCodePoint > 57343)) { | ||
codePoint = tempCodePoint; | ||
} | ||
} | ||
break; | ||
case 4: | ||
secondByte = buf[offset + 1]; | ||
thirdByte = buf[offset + 2]; | ||
fourthByte = buf[offset + 3]; | ||
if ((secondByte & 192) === 128 && (thirdByte & 192) === 128 && (fourthByte & 192) === 128) { | ||
tempCodePoint = (firstByte & 15) << 18 | (secondByte & 63) << 12 | (thirdByte & 63) << 6 | fourthByte & 63; | ||
if (tempCodePoint > 65535 && tempCodePoint < 1114112) { | ||
codePoint = tempCodePoint; | ||
} | ||
} | ||
} | ||
} | ||
if (codePoint === null) { | ||
codePoint = 65533; | ||
bytesPerSequence = 1; | ||
} else if (codePoint > 65535) { | ||
codePoint -= 65536; | ||
res.push(codePoint >>> 10 & 1023 | 55296); | ||
codePoint = 56320 | codePoint & 1023; | ||
} | ||
res.push(codePoint); | ||
offset += bytesPerSequence; | ||
} | ||
return decodeCodePointsArray(res); | ||
} | ||
const MAX_ARGUMENTS_LENGTH = 4096; | ||
function decodeCodePointsArray(codePoints) { | ||
const len = codePoints.length; | ||
if (len <= MAX_ARGUMENTS_LENGTH) { | ||
return String.fromCharCode.apply(String, codePoints); | ||
} | ||
let res = ''; | ||
let i = 0; | ||
while (i < len) { | ||
res += String.fromCharCode.apply(String, codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH)); | ||
} | ||
return res; | ||
} |
@@ -25,3 +25,3 @@ import { decodeErrPrefix } from './common.js'; | ||
let token = quick[byt]; | ||
if (!token) { | ||
if (token === undefined) { | ||
const decoder = jump[byt]; | ||
@@ -28,0 +28,0 @@ if (!decoder) { |
@@ -101,11 +101,16 @@ import is from './is.js'; | ||
refStack = Ref.createCheck(refStack, obj); | ||
const ret = [new Token(Type.array, obj.length)]; | ||
for (let i = 0; i < obj.length; i++) { | ||
ret[i + 1] = objectToTokens(obj[i], options, refStack); | ||
const entries = []; | ||
let i = 0; | ||
for (const e of obj) { | ||
entries[i++] = objectToTokens(e, options, refStack); | ||
} | ||
return ret; | ||
return [ | ||
new Token(Type.array, obj.length), | ||
entries | ||
]; | ||
}, | ||
Object(obj, typ, options, refStack) { | ||
const entriesIter = typ === 'Object' ? Object.entries(obj) : obj.entries(); | ||
const length = typ === 'Object' ? entriesIter.length : obj.size; | ||
const isMap = typ !== 'Object'; | ||
const keys = isMap ? obj.keys() : Object.keys(obj); | ||
const length = isMap ? obj.size : keys.length; | ||
if (!length) { | ||
@@ -117,11 +122,13 @@ return simpleTokens.emptyMap; | ||
let i = 0; | ||
for (const [key, value] of entriesIter) { | ||
for (const key of keys) { | ||
entries[i++] = [ | ||
objectToTokens(key, options, refStack), | ||
objectToTokens(value, options, refStack) | ||
objectToTokens(isMap ? obj.get(key) : obj[key], options, refStack) | ||
]; | ||
} | ||
sortMapEntries(entries); | ||
entries.unshift(new Token(Type.map, length)); | ||
return entries; | ||
entries.sort(mapSorter); | ||
return [ | ||
new Token(Type.map, length), | ||
entries | ||
]; | ||
} | ||
@@ -149,11 +156,7 @@ }; | ||
} | ||
function sortMapEntries(entries) { | ||
entries.sort(mapSorter); | ||
} | ||
function mapSorter(e1, e2) { | ||
const keyToken1 = Array.isArray(e1[0]) ? e1[0][0] : e1[0]; | ||
const keyToken2 = Array.isArray(e2[0]) ? e2[0][0] : e2[0]; | ||
const mcmp = keyToken1.type.compare(keyToken2.type); | ||
if (mcmp !== 0) { | ||
return mcmp; | ||
if (keyToken1.type !== keyToken2.type) { | ||
return keyToken1.type.compare(keyToken2.type); | ||
} | ||
@@ -168,16 +171,9 @@ const major = keyToken1.type.major; | ||
function tokensToEncoded(buf, tokens, options) { | ||
const it = tokens => { | ||
if (Array.isArray(tokens)) { | ||
for (const token of tokens) { | ||
enc(token); | ||
tokensToEncoded(buf, token, options); | ||
} | ||
}; | ||
const enc = token => { | ||
if (Array.isArray(token)) { | ||
it(token); | ||
} else { | ||
const length = encoders[token.type.major](buf, token, options); | ||
buf.increment(length); | ||
} | ||
}; | ||
enc(tokens); | ||
} else { | ||
encoders[tokens.type.major](buf, tokens, options); | ||
} | ||
} | ||
@@ -196,6 +192,3 @@ function encode(data, options) { | ||
const buf = new Bl(size); | ||
const encodedSize = encoder(buf, tokens, options); | ||
if (encodedSize !== size) { | ||
throw new Error(`Unexpected error: pre-calculated length for ${ tokens } was wrong`); | ||
} | ||
encoder(buf, tokens, options); | ||
if (buf.chunks.length !== 1) { | ||
@@ -202,0 +195,0 @@ throw new Error(`Unexpected error: pre-calculated length for ${ tokens } was wrong`); |
@@ -5,202 +5,81 @@ import chai from 'chai'; | ||
describe('Internal bytes list', () => { | ||
it('sets bits, individually incremented', () => { | ||
const bl = new Bl(10); | ||
const expected = []; | ||
for (let i = 0; i < 25; i++) { | ||
bl.set(0, i + 1); | ||
assert.strictEqual(bl.get(0), i + 1); | ||
bl.increment(1); | ||
expected.push(i + 1); | ||
} | ||
assert.deepEqual([...bl.toBytes()], expected); | ||
}); | ||
it('sets bits, bulk incremented', () => { | ||
const bl = new Bl(10); | ||
const expected = []; | ||
for (let i = 0; i < 25; i++) { | ||
bl.set(i, i + 1); | ||
assert.strictEqual(bl.get(i), i + 1); | ||
expected.push(i + 1); | ||
} | ||
assert.deepEqual([...bl.toBytes()], []); | ||
for (let i = 0; i < 5; i++) { | ||
assert.strictEqual(bl.get(i), expected[i]); | ||
} | ||
bl.increment(5); | ||
assert.deepEqual([...bl.toBytes()].slice(0, 5), expected.slice(0, 5)); | ||
bl.increment(20); | ||
assert.deepEqual([...bl.toBytes()], expected); | ||
}); | ||
it('sets bits, partial progressive increment', () => { | ||
const bl = new Bl(10); | ||
const expected = []; | ||
for (let i = 0; i < 25; i++) { | ||
bl.set(i % 5, i + 1); | ||
assert.strictEqual(bl.get(i % 5), i + 1); | ||
expected.push(i + 1); | ||
if (i % 5 === 4) { | ||
bl.increment(5); | ||
describe('push', () => { | ||
it('push bits', () => { | ||
const bl = new Bl(10); | ||
const expected = []; | ||
for (let i = 0; i < 25; i++) { | ||
bl.push([i + 1]); | ||
expected.push(i + 1); | ||
} | ||
assert.deepEqual([...bl.toBytes()], expected); | ||
}); | ||
for (let i = 4; i < 21; i++) { | ||
it(`push Bl(${ i })`, () => { | ||
const bl = new Bl(i); | ||
const expected = [ | ||
1, | ||
2, | ||
3, | ||
4, | ||
5, | ||
6, | ||
7, | ||
8, | ||
9, | ||
10, | ||
100, | ||
110, | ||
120, | ||
11, | ||
12, | ||
130, | ||
13, | ||
14, | ||
15, | ||
16, | ||
17, | ||
18, | ||
19, | ||
20, | ||
21, | ||
22, | ||
23 | ||
]; | ||
for (let i = 0; i < 5; i++) { | ||
bl.push([i + 1]); | ||
} | ||
bl.push(Uint8Array.from([ | ||
6, | ||
7, | ||
8, | ||
9, | ||
10 | ||
])); | ||
bl.push([100]); | ||
bl.push(Uint8Array.from([ | ||
110, | ||
120 | ||
])); | ||
bl.push(Uint8Array.from([ | ||
11, | ||
12 | ||
])); | ||
bl.push([130]); | ||
bl.push(Uint8Array.from([ | ||
13, | ||
14, | ||
15, | ||
16, | ||
17, | ||
18, | ||
19, | ||
20, | ||
21, | ||
22, | ||
23 | ||
])); | ||
assert.deepEqual([...bl.toBytes()], expected); | ||
}); | ||
} | ||
assert.deepEqual([...bl.toBytes()], expected); | ||
}); | ||
it('copyTo, easy path', () => { | ||
const bl = new Bl(20); | ||
const expected = [ | ||
1, | ||
2, | ||
3, | ||
4, | ||
5, | ||
6, | ||
100, | ||
110, | ||
120, | ||
10, | ||
11, | ||
12, | ||
13 | ||
]; | ||
for (let i = 0; i < 5; i++) { | ||
bl.set(0, i + 1); | ||
assert.strictEqual(bl.get(0), i + 1); | ||
bl.increment(1); | ||
} | ||
bl.copyTo(0, Uint8Array.from([ | ||
6, | ||
7, | ||
8, | ||
9, | ||
10 | ||
])); | ||
bl.set(1, 100); | ||
bl.copyTo(2, Uint8Array.from([ | ||
110, | ||
120 | ||
])); | ||
for (let i = 0; i < 5; i++) { | ||
assert.strictEqual(bl.get(i), expected[i + 5]); | ||
} | ||
bl.increment(5); | ||
bl.copyTo(0, Uint8Array.from([ | ||
11, | ||
12 | ||
])); | ||
assert.strictEqual(bl.get(0), expected[10]); | ||
assert.strictEqual(bl.get(1), expected[11]); | ||
bl.increment(2); | ||
bl.set(0, 13); | ||
assert.strictEqual(bl.get(0), 13); | ||
bl.increment(1); | ||
assert.deepEqual([...bl.toBytes()], expected); | ||
}); | ||
it('copyTo, splice', () => { | ||
const bl = new Bl(4); | ||
const expected = [ | ||
1, | ||
2, | ||
3, | ||
4, | ||
5, | ||
6, | ||
100, | ||
110, | ||
120, | ||
10, | ||
11, | ||
12, | ||
13 | ||
]; | ||
for (let i = 0; i < 5; i++) { | ||
bl.set(0, i + 1); | ||
assert.strictEqual(bl.get(0), i + 1); | ||
bl.increment(1); | ||
} | ||
bl.copyTo(0, Uint8Array.from([ | ||
6, | ||
7, | ||
8, | ||
9, | ||
10 | ||
])); | ||
bl.set(1, 100); | ||
bl.copyTo(2, Uint8Array.from([ | ||
110, | ||
120 | ||
])); | ||
for (let i = 0; i < 5; i++) { | ||
assert.strictEqual(bl.get(i), expected[i + 5]); | ||
} | ||
bl.increment(5); | ||
bl.copyTo(0, Uint8Array.from([ | ||
11, | ||
12 | ||
])); | ||
assert.strictEqual(bl.get(0), expected[10]); | ||
assert.strictEqual(bl.get(1), expected[11]); | ||
bl.increment(2); | ||
bl.set(0, 13); | ||
assert.strictEqual(bl.get(0), 13); | ||
bl.increment(1); | ||
assert.deepEqual([...bl.toBytes()], expected); | ||
}); | ||
it('copyTo, insert', () => { | ||
const bl = new Bl(4); | ||
const expected = [ | ||
1, | ||
2, | ||
3, | ||
4, | ||
5, | ||
6, | ||
100, | ||
110, | ||
120, | ||
10, | ||
11, | ||
12, | ||
13, | ||
14, | ||
15, | ||
16, | ||
17 | ||
]; | ||
for (let i = 0; i < 5; i++) { | ||
bl.set(0, i + 1); | ||
assert.strictEqual(bl.get(0), i + 1); | ||
bl.increment(1); | ||
} | ||
bl.copyTo(0, Uint8Array.from([ | ||
6, | ||
7, | ||
8, | ||
9, | ||
10 | ||
])); | ||
bl.set(1, 100); | ||
bl.copyTo(2, Uint8Array.from([ | ||
110, | ||
120 | ||
])); | ||
for (let i = 0; i < 5; i++) { | ||
assert.strictEqual(bl.get(i), expected[i + 5]); | ||
} | ||
bl.increment(5); | ||
bl.copyTo(0, Uint8Array.from([ | ||
11, | ||
12, | ||
13, | ||
14, | ||
15, | ||
16 | ||
])); | ||
for (let i = 0; i < 6; i++) { | ||
assert.strictEqual(bl.get(i), expected[i + 10]); | ||
} | ||
bl.increment(6); | ||
bl.set(0, 17); | ||
assert.strictEqual(bl.get(0), 17); | ||
bl.increment(1); | ||
assert.deepEqual([...bl.toBytes()], expected); | ||
}); | ||
}); |
{ | ||
"name": "cborg", | ||
"version": "1.0.2", | ||
"version": "1.0.3", | ||
"description": "Fast CBOR with a focus on strictness", | ||
@@ -10,3 +10,3 @@ "bin": { | ||
"lint": "standard *.js lib/*.js test/*.js", | ||
"build": "npx ipjs@latest build --tests && cp cli.js dist/", | ||
"build": "npx ipjs build --tests && cp cli.js dist/", | ||
"test:cjs": "npm run build && mocha dist/cjs/node-test/test-*.js dist/cjs/node-test/node-test-*.js", | ||
@@ -30,3 +30,3 @@ "test:node": "c8 --check-coverage --branches 100 --functions 100 --lines 100 mocha test/test-*.js test/node-test-*.js", | ||
"chai": "^4.2.0", | ||
"ipld-garbage": "^1.0.3", | ||
"ipld-garbage": "^2.0.0", | ||
"mocha": "^8.2.1", | ||
@@ -33,0 +33,0 @@ "polendina": "^1.1.0", |
410446
14148