From 36a01e50f1ea910364d98e83d17ea81397152c0f Mon Sep 17 00:00:00 2001 From: Rod Vagg Date: Tue, 12 Sep 2023 13:28:09 +1000 Subject: [PATCH] feat: encodeInto(obj, dest, [options]) --- bench/bench.js | 17 ++++++++++++++-- cborg.js | 3 ++- interface.ts | 8 +++++++- lib/bl.js | 40 ++++++++++++++++++++++++++++++++++++++ lib/encode.js | 41 ++++++++++++++++++++++++++++----------- test/test-0uint.js | 7 ++++++- test/test-1negint.js | 7 ++++++- test/test-2bytes.js | 6 +++++- test/test-3string.js | 6 +++++- test/test-4array.js | 6 +++++- test/test-5map.js | 8 +++++--- test/test-6tag.js | 14 ++++++++++++- test/test-7float.js | 6 +++++- test/test-cbor-vectors.js | 9 +++++++-- types/cborg.d.ts | 3 ++- types/cborg.d.ts.map | 2 +- types/interface.d.ts | 7 ++++++- types/interface.d.ts.map | 2 +- types/lib/bl.d.ts | 21 ++++++++++++++++++++ types/lib/bl.d.ts.map | 2 +- types/lib/encode.d.ts | 11 ++++++++++- types/lib/encode.d.ts.map | 2 +- 22 files changed, 194 insertions(+), 34 deletions(-) diff --git a/bench/bench.js b/bench/bench.js index ec98c60..026399a 100644 --- a/bench/bench.js +++ b/bench/bench.js @@ -3,9 +3,11 @@ import assert from 'assert' import { garbage } from 'ipld-garbage' -import { decode, encode } from '../cborg.js' +import { decode, encode, encodeInto } from '../cborg.js' import borc from 'borc' +const WITH_CBORG_FIXED_DESTINATION = true + let writebuf = '' const write = process.stdout ? process.stdout.write.bind(process.stdout) @@ -27,6 +29,17 @@ function runWith (description, count, targetTime, size, options) { return borcDecoder.decodeAll(bytes)[0] } + let cborgEncoder = WITH_CBORG_FIXED_DESTINATION ? null : encode + + const cborgEncode = (bytes) => { + if (!cborgEncoder) { + // account for initial allocation & setup time in benchmark + const fixedDestination = new Uint8Array(10 * 1024 * 1024) + cborgEncoder = (bytes) => encodeInto(bytes, fixedDestination) + } + return cborgEncoder(bytes) + } + const fixtures = [] console.log(`${description} @ ${count.toLocaleString()}`) @@ -91,7 +104,7 @@ function runWith (description, count, targetTime, size, options) { } return [ - cmp('encode', () => enc(encode), () => enc(borc.encode)), + cmp('encode', () => enc(cborgEncode), () => enc(borc.encode)), cmp('decode', () => dec(decode), () => dec(borcDecode)) ] } diff --git a/cborg.js b/cborg.js index 90bde20..4a0f179 100644 --- a/cborg.js +++ b/cborg.js @@ -1,4 +1,4 @@ -import { encode } from './lib/encode.js' +import { encode, encodeInto } from './lib/encode.js' import { decode, decodeFirst } from './lib/decode.js' import { Token, Type } from './lib/token.js' @@ -15,6 +15,7 @@ export { decode, decodeFirst, encode, + encodeInto, Token, Type } diff --git a/interface.ts b/interface.ts index 020264d..51c1099 100644 --- a/interface.ts +++ b/interface.ts @@ -1,5 +1,4 @@ import { Token } from './lib/token' -import { Bl } from './lib/bl' export type TokenOrNestedTokens = Token | Token[] | TokenOrNestedTokens[] @@ -54,3 +53,10 @@ export interface EncodeOptions { quickEncodeToken?: QuickEncodeToken, typeEncoders?: { [typeName: string]: OptionalTypeEncoder } } + +export interface Bl { + chunks: (Uint8Array | number[])[]; + reset(): void; + push(bytes: Uint8Array | number[]): void; + toBytes(reset?: boolean | undefined): Uint8Array; +} diff --git a/lib/bl.js b/lib/bl.js index af974de..cefb8b4 100644 --- a/lib/bl.js +++ b/lib/bl.js @@ -122,3 +122,43 @@ export class Bl { return byts } } + +export class U8Bl { + /** + * @param {Uint8Array} dest + */ + constructor (dest) { + this.dest = dest + /** @type {number} */ + this.cursor = 0 + /** @type {Uint8Array[]} */ + this.chunks = [dest] + } + + reset () { + this.cursor = 0 + } + + /** + * @param {Uint8Array|number[]} bytes + */ + push (bytes) { + if (this.cursor + bytes.length > this.dest.length) { + throw new Error('write out of bounds, destination buffer is too small') + } + this.dest.set(bytes, this.cursor) + this.cursor += bytes.length + } + + /** + * @param {boolean} [reset] + * @returns {Uint8Array} + */ + toBytes (reset = false) { + const byts = this.dest.subarray(0, this.cursor) + if (reset) { + this.reset() + } + return byts + } +} diff --git a/lib/encode.js b/lib/encode.js index acd7bac..61b6c29 100644 --- a/lib/encode.js +++ b/lib/encode.js @@ -1,6 +1,6 @@ import { is } from './is.js' import { Token, Type } from './token.js' -import { Bl } from './bl.js' +import { Bl as _Bl, U8Bl } from './bl.js' import { encodeErrPrefix } from './common.js' import { quickEncodeToken } from './jump.js' import { asU8A } from './byte-utils.js' @@ -21,6 +21,7 @@ import { encodeFloat } from './7float.js' * @typedef {import('../interface').StrictTypeEncoder} StrictTypeEncoder * @typedef {import('../interface').TokenTypeEncoder} TokenTypeEncoder * @typedef {import('../interface').TokenOrNestedTokens} TokenOrNestedTokens + * @typedef {import('../interface').Bl} Bl */ /** @type {EncodeOptions} */ @@ -46,7 +47,7 @@ export function makeCborEncoders () { const cborEncoders = makeCborEncoders() -const buf = new Bl() +const buf = new _Bl() /** @implements {Reference} */ class Ref { @@ -424,9 +425,14 @@ function tokensToEncoded (buf, tokens, encoders, options) { * @param {any} data * @param {TokenTypeEncoder[]} encoders * @param {EncodeOptions} options + * @param {Uint8Array} [destination] * @returns {Uint8Array} */ -function encodeCustom (data, encoders, options) { +function encodeCustom (data, encoders, options, destination) { + // arg ordering is different to encodeInto for backward compatibility + const hasDest = destination instanceof Uint8Array + let writeTo = hasDest ? new U8Bl(destination) : buf + const tokens = objectToTokens(data, options) if (!Array.isArray(tokens) && options.quickEncodeToken) { const quickBytes = options.quickEncodeToken(tokens) @@ -436,19 +442,21 @@ function encodeCustom (data, encoders, options) { const encoder = encoders[tokens.type.major] if (encoder.encodedSize) { const size = encoder.encodedSize(tokens, options) - const buf = new Bl(size) - encoder(buf, tokens, options) + if (!hasDest) { + writeTo = new _Bl(size) + } + encoder(writeTo, tokens, options) /* c8 ignore next 4 */ // this would be a problem with encodedSize() functions - if (buf.chunks.length !== 1) { + if (writeTo.chunks.length !== 1) { throw new Error(`Unexpected error: pre-calculated length for ${tokens} was wrong`) } - return asU8A(buf.chunks[0]) + return hasDest ? writeTo.toBytes() : asU8A(writeTo.chunks[0]) } } - buf.reset() - tokensToEncoded(buf, tokens, encoders, options) - return buf.toBytes(true) + writeTo.reset() + tokensToEncoded(writeTo, tokens, encoders, options) + return writeTo.toBytes(true) } /** @@ -461,4 +469,15 @@ function encode (data, options) { return encodeCustom(data, cborEncoders, options) } -export { objectToTokens, encode, encodeCustom, Ref } +/** + * @param {any} data + * @param {Uint8Array} destination + * @param {EncodeOptions} [options] + * @returns {Uint8Array} + */ +function encodeInto (data, destination, options) { + options = Object.assign({}, defaultEncodeOptions, options) + return encodeCustom(data, cborEncoders, options, destination) +} + +export { objectToTokens, encode, encodeCustom, encodeInto, Ref } diff --git a/test/test-0uint.js b/test/test-0uint.js index da3b04b..11f91d5 100644 --- a/test/test-0uint.js +++ b/test/test-0uint.js @@ -2,7 +2,7 @@ import chai from 'chai' -import { decode, encode } from '../cborg.js' +import { decode, encode, encodeInto } from '../cborg.js' import { fromHex, toHex } from '../lib/byte-utils.js' const { assert } = chai @@ -27,6 +27,8 @@ const fixtures = [ { data: '1bffffffffffffffff', expected: BigInt('18446744073709551615'), type: 'uint64' } ] +const fixedDest = new Uint8Array(1024) + describe('uint', () => { describe('decode', () => { for (const fixture of fixtures) { @@ -53,8 +55,10 @@ describe('uint', () => { it(`should encode ${fixture.type}=${fixture.expected}`, () => { if (fixture.strict === false) { assert.notStrictEqual(toHex(encode(fixture.expected)), fixture.data, `encode ${fixture.type} !strict`) + assert.notStrictEqual(toHex(encodeInto(fixture.expected, fixedDest)), fixture.data, `encode ${fixture.type} !strict`) } else { assert.strictEqual(toHex(encode(fixture.expected)), fixture.data, `encode ${fixture.type}`) + assert.strictEqual(toHex(encodeInto(fixture.expected, fixedDest)), fixture.data, `encode ${fixture.type}`) } }) } @@ -66,6 +70,7 @@ describe('uint', () => { if (fixture.strict !== false) { it(`should roundtrip ${fixture.type}=${fixture.expected}`, () => { assert.ok(decode(encode(fixture.expected)) === fixture.expected, `roundtrip ${fixture.type}`) + assert.ok(decode(encodeInto(fixture.expected, fixedDest)) === fixture.expected, `roundtrip ${fixture.type}`) }) } } diff --git a/test/test-1negint.js b/test/test-1negint.js index 13b8819..b86958b 100644 --- a/test/test-1negint.js +++ b/test/test-1negint.js @@ -2,7 +2,7 @@ import chai from 'chai' -import { decode, encode } from '../cborg.js' +import { decode, encode, encodeInto } from '../cborg.js' import { fromHex, toHex } from '../lib/byte-utils.js' const { assert } = chai @@ -28,6 +28,8 @@ const fixtures = [ { data: '3bffffffffffffffff', expected: BigInt('-18446744073709551616'), type: 'negint64' } ] +const fixedDest = new Uint8Array(1024) + describe('negint', () => { describe('decode', () => { for (const fixture of fixtures) { @@ -48,8 +50,10 @@ describe('negint', () => { it(`should encode ${fixture.type}=${fixture.expected}`, () => { if (fixture.strict === false) { assert.notStrictEqual(toHex(encode(fixture.expected)), fixture.data, `encode ${fixture.type} !strict`) + assert.notStrictEqual(toHex(encodeInto(fixture.expected, fixedDest)), fixture.data, `encode ${fixture.type} !strict`) } else { assert.strictEqual(toHex(encode(fixture.expected)), fixture.data, `encode ${fixture.type}`) + assert.strictEqual(toHex(encodeInto(fixture.expected, fixedDest)), fixture.data, `encode ${fixture.type}`) } }) } @@ -60,6 +64,7 @@ describe('negint', () => { for (const fixture of fixtures) { it(`should roundtrip ${fixture.type}=${fixture.expected}`, () => { assert.ok(decode(encode(fixture.expected)) === fixture.expected, `roundtrip ${fixture.type}`) + assert.ok(decode(encodeInto(fixture.expected, fixedDest)) === fixture.expected, `roundtrip ${fixture.type}`) }) } }) diff --git a/test/test-2bytes.js b/test/test-2bytes.js index a075999..2475241 100644 --- a/test/test-2bytes.js +++ b/test/test-2bytes.js @@ -2,7 +2,7 @@ import chai from 'chai' -import { decode, encode } from '../cborg.js' +import { decode, encode, encodeInto } from '../cborg.js' import { useBuffer, fromHex, toHex } from '../lib/byte-utils.js' const { assert } = chai @@ -42,6 +42,8 @@ const fixtures = [ } ] +const fixedDest = new Uint8Array(65536 + 8) + // fill up byte arrays we can validate in strict mode, the minimal size for each // excluding 64-bit because 4G is just too big ;(() => { @@ -111,8 +113,10 @@ describe('bytes', () => { assert.throws(() => encode(data), Error, /^CBOR encode error: number too large to encode \(-\d+\)$/) } else if (fixture.strict === false) { assert.notStrictEqual(toHex(encode(data)), expectedHex, `encode ${fixture.type} !strict`) + assert.notStrictEqual(toHex(encodeInto(data, fixedDest)), expectedHex, `encode ${fixture.type} !strict`) } else { assert.strictEqual(toHex(encode(data)), expectedHex, `encode ${fixture.type}`) + assert.strictEqual(toHex(encodeInto(data, fixedDest)), expectedHex, `encode ${fixture.type}`) } }) } diff --git a/test/test-3string.js b/test/test-3string.js index e906e67..47871c2 100644 --- a/test/test-3string.js +++ b/test/test-3string.js @@ -2,7 +2,7 @@ import chai from 'chai' -import { decode, encode } from '../cborg.js' +import { decode, encode, encodeInto } from '../cborg.js' import { fromHex, toHex } from '../lib/byte-utils.js' const { assert } = chai @@ -52,6 +52,8 @@ const fixtures = [ } ] +const fixedDest = new Uint8Array(65536 + 8) + // fill up byte arrays converted to strings so we can validate in strict mode, // the minimal size for each excluding 64-bit because 4G is just too big ;(() => { @@ -127,8 +129,10 @@ describe('string', () => { assert.throws(() => encode(data), Error, /^CBOR encode error: number too large to encode \(-\d+\)$/) } else if (fixture.strict === false) { assert.notStrictEqual(toHex(encode(data)), expectedHex, `encode ${fixture.type} !strict`) + assert.notStrictEqual(toHex(encodeInto(data, fixedDest)), expectedHex, `encode ${fixture.type} !strict`) } else { assert.strictEqual(toHex(encode(data)), expectedHex, `encode ${fixture.type}`) + assert.strictEqual(toHex(encodeInto(data, fixedDest)), expectedHex, `encode ${fixture.type}`) } }) } diff --git a/test/test-4array.js b/test/test-4array.js index 2cc823a..c2b6268 100644 --- a/test/test-4array.js +++ b/test/test-4array.js @@ -2,7 +2,7 @@ import chai from 'chai' -import { decode, encode } from '../cborg.js' +import { decode, encode, encodeInto } from '../cborg.js' import { fromHex, toHex } from '../lib/byte-utils.js' const { assert } = chai @@ -35,6 +35,8 @@ const fixtures = [ { data: '9b000000000000000403040506', expected: [3, 4, 5, 6], type: 'array 4 ints, length64', strict: false } ] +const fixedDest = new Uint8Array(1024) + describe('array', () => { describe('decode', () => { for (const fixture of fixtures) { @@ -63,8 +65,10 @@ describe('array', () => { assert.throws(encode.bind(null, fixture.expected), Error, /^CBOR encode error: number too large to encode \(\d+\)$/) } else if (fixture.strict === false) { assert.notDeepEqual(toHex(encode(fixture.expected)), fixture.data, `encode ${fixture.type} !strict`) + assert.notDeepEqual(toHex(encodeInto(fixture.expected, fixedDest)), fixture.data, `encode ${fixture.type} !strict`) } else { assert.strictEqual(toHex(encode(fixture.expected)), fixture.data, `encode ${fixture.type}`) + assert.strictEqual(toHex(encodeInto(fixture.expected, fixedDest)), fixture.data, `encode ${fixture.type}`) } }) } diff --git a/test/test-5map.js b/test/test-5map.js index 95e2278..a25d389 100644 --- a/test/test-5map.js +++ b/test/test-5map.js @@ -2,7 +2,7 @@ import chai from 'chai' -import { decode, encode } from '../cborg.js' +import { decode, encode, encodeInto } from '../cborg.js' import { fromHex, toHex } from '../lib/byte-utils.js' const { assert } = chai @@ -133,6 +133,8 @@ const fixtures = [ { data: 'bb0000000000000001616101', expected: { a: 1 }, type: 'map 1 pair, length64', strict: false } ] +const fixedDest = new Uint8Array(1024) + function toMap (arr) { const m = new Map() for (const [key, value] of arr) { @@ -205,9 +207,9 @@ describe('map', () => { if (fixture.unsafe) { assert.throws(encode.bind(null, toEncode), Error, /^CBOR encode error: number too large to encode \(\d+\)$/) } else if (fixture.strict === false || fixture.roundtrip === false) { - assert.notDeepEqual(toHex(encode(toEncode)), fixture.data, `encode ${fixture.type} !strict`) + assert.notDeepEqual(toHex(encodeInto(toEncode, fixedDest)), fixture.data, `encode ${fixture.type} !strict`) } else { - assert.strictEqual(toHex(encode(toEncode)), fixture.data, `encode ${fixture.type}`) + assert.strictEqual(toHex(encodeInto(toEncode, fixedDest)), fixture.data, `encode ${fixture.type}`) } }) } diff --git a/test/test-6tag.js b/test/test-6tag.js index 0a3b105..5d85dab 100644 --- a/test/test-6tag.js +++ b/test/test-6tag.js @@ -3,12 +3,14 @@ import chai from 'chai' import { Token, Type } from '../lib/token.js' -import { decode, encode } from '../cborg.js' +import { decode, encode, encodeInto } from '../cborg.js' import { fromHex, toHex } from '../lib/byte-utils.js' import { dateDecoder, dateEncoder } from './common.js' const { assert } = chai +const fixedDest = new Uint8Array(1024) + function Uint16ArrayDecoder (obj) { if (typeof obj !== 'string') { throw new Error('expected string for tag 23') @@ -36,6 +38,11 @@ describe('tag', () => { 'c074323031332d30332d32315432303a30343a30305a' // from appendix_a ) + assert.equal( + toHex(encodeInto(new Date('2013-03-21T20:04:00Z'), fixedDest, { typeEncoders: { Date: dateEncoder } })), + 'c074323031332d30332d32315432303a30343a30305a' // from appendix_a + ) + const decodedDate = decode(fromHex('c074323031332d30332d32315432303a30343a30305a'), { tags: { 0: dateDecoder } }) assert.instanceOf(decodedDate, Date) assert.equal(decodedDate.toISOString(), new Date('2013-03-21T20:04:00Z').toISOString()) @@ -47,6 +54,11 @@ describe('tag', () => { 'd76c303130303032303030333030' // tag(23) + string('010002000300') ) + assert.equal( + toHex(encodeInto(Uint16Array.from([1, 2, 3]), fixedDest, { typeEncoders: { Uint16Array: Uint16ArrayEncoder } })), + 'd76c303130303032303030333030' // tag(23) + string('010002000300') + ) + const decoded = decode(fromHex('d76c303130303032303030333030'), { tags: { 23: Uint16ArrayDecoder } }) assert.instanceOf(decoded, Uint16Array) assert.equal(toHex(decoded), toHex(Uint16Array.from([1, 2, 3]))) diff --git a/test/test-7float.js b/test/test-7float.js index f4d0079..4a5038c 100644 --- a/test/test-7float.js +++ b/test/test-7float.js @@ -2,7 +2,7 @@ import chai from 'chai' -import { decode, encode } from '../cborg.js' +import { decode, encode, encodeInto } from '../cborg.js' import { fromHex, toHex } from '../lib/byte-utils.js' const { assert } = chai @@ -32,6 +32,8 @@ const fixtures = [ { data: 'fb40f4241a31a5a515', expected: 82497.63712086187, type: 'float64' } ] +const fixedDest = new Uint8Array(1024) + describe('float', () => { describe('decode', () => { for (const fixture of fixtures) { @@ -56,6 +58,7 @@ describe('float', () => { if (fixture.strict !== false) { it(`should encode ${fixture.type}=${fixture.expected}`, () => { assert.strictEqual(toHex(encode(fixture.expected)), fixture.data, `encode ${fixture.type}`) + assert.strictEqual(toHex(encodeInto(fixture.expected, fixedDest)), fixture.data, `encode ${fixture.type}`) }) } } @@ -79,6 +82,7 @@ describe('float', () => { if (!fixture.unsafe && fixture.strict !== false) { it(`should roundtrip ${fixture.type}=${fixture.expected}`, () => { assert.deepStrictEqual(decode(encode(fixture.expected)), fixture.expected, `roundtrip ${fixture.type}`) + assert.deepStrictEqual(decode(encodeInto(fixture.expected, fixedDest)), fixture.expected, `roundtrip ${fixture.type}`) }) } } diff --git a/test/test-cbor-vectors.js b/test/test-cbor-vectors.js index 8fc2d96..ae65e92 100644 --- a/test/test-cbor-vectors.js +++ b/test/test-cbor-vectors.js @@ -2,7 +2,7 @@ import chai from 'chai' -import { decode, encode } from '../cborg.js' +import { decode, encode, encodeInto } from '../cborg.js' import * as taglib from 'cborg/taglib' import { fromHex, toHex } from '../lib/byte-utils.js' // fixtures from https://github.com/cbor/test-vectors @@ -10,6 +10,8 @@ import { fixtures } from './appendix_a.js' const { assert } = chai +const fixedDest = new Uint8Array(1024) + const tags = [] const typeEncoders = {} @@ -80,8 +82,11 @@ describe('cbor/test-vectors', () => { if (fixture.roundtrip) { if (fixture.noTagEncodeError) { assert.throws(() => encode(decode(u8a, { tags })), fixture.noTagEncodeError) + assert.throws(() => encodeInto(decode(u8a, { tags }), fixedDest), fixture.noTagEncodeError) } - const reencoded = encode(decode(u8a, { tags }), { typeEncoders }) + let reencoded = encode(decode(u8a, { tags }), { typeEncoders }) + assert.equal(toHex(reencoded), fixture.hex) + reencoded = encodeInto(decode(u8a, { tags }), fixedDest, { typeEncoders }) assert.equal(toHex(reencoded), fixture.hex) } } diff --git a/types/cborg.d.ts b/types/cborg.d.ts index 1f8711a..37935a1 100644 --- a/types/cborg.d.ts +++ b/types/cborg.d.ts @@ -17,7 +17,8 @@ export type EncodeOptions = import('./interface').EncodeOptions; import { decode } from './lib/decode.js'; import { decodeFirst } from './lib/decode.js'; import { encode } from './lib/encode.js'; +import { encodeInto } from './lib/encode.js'; import { Token } from './lib/token.js'; import { Type } from './lib/token.js'; -export { decode, decodeFirst, encode, Token, Type }; +export { decode, decodeFirst, encode, encodeInto, Token, Type }; //# sourceMappingURL=cborg.d.ts.map \ No newline at end of file diff --git a/types/cborg.d.ts.map b/types/cborg.d.ts.map index a8c1dbf..a2a91a8 100644 --- a/types/cborg.d.ts.map +++ b/types/cborg.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"cborg.d.ts","sourceRoot":"","sources":["../cborg.js"],"names":[],"mappings":";;;yBAMa,OAAO,aAAa,EAAE,UAAU;;;;0BAEhC,OAAO,aAAa,EAAE,mBAAmB;;;;4BACzC,OAAO,aAAa,EAAE,aAAa;;;;4BACnC,OAAO,aAAa,EAAE,aAAa;uBATZ,iBAAiB;4BAAjB,iBAAiB;uBAD9B,iBAAiB;sBAEZ,gBAAgB;qBAAhB,gBAAgB"} \ No newline at end of file +{"version":3,"file":"cborg.d.ts","sourceRoot":"","sources":["../cborg.js"],"names":[],"mappings":";;;yBAMa,OAAO,aAAa,EAAE,UAAU;;;;0BAEhC,OAAO,aAAa,EAAE,mBAAmB;;;;4BACzC,OAAO,aAAa,EAAE,aAAa;;;;4BACnC,OAAO,aAAa,EAAE,aAAa;uBATZ,iBAAiB;4BAAjB,iBAAiB;uBADlB,iBAAiB;2BAAjB,iBAAiB;sBAExB,gBAAgB;qBAAhB,gBAAgB"} \ No newline at end of file diff --git a/types/interface.d.ts b/types/interface.d.ts index 40b734f..4bcf450 100644 --- a/types/interface.d.ts +++ b/types/interface.d.ts @@ -1,5 +1,4 @@ import { Token } from './lib/token'; -import { Bl } from './lib/bl'; export type TokenOrNestedTokens = Token | Token[] | TokenOrNestedTokens[]; export interface Reference { parent: Reference | undefined; @@ -44,4 +43,10 @@ export interface EncodeOptions { [typeName: string]: OptionalTypeEncoder; }; } +export interface Bl { + chunks: (Uint8Array | number[])[]; + reset(): void; + push(bytes: Uint8Array | number[]): void; + toBytes(reset?: boolean | undefined): Uint8Array; +} //# sourceMappingURL=interface.d.ts.map \ No newline at end of file diff --git a/types/interface.d.ts.map b/types/interface.d.ts.map index b975497..0fd25ca 100644 --- a/types/interface.d.ts.map +++ b/types/interface.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"interface.d.ts","sourceRoot":"","sources":["../interface.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AACnC,OAAO,EAAE,EAAE,EAAE,MAAM,UAAU,CAAA;AAE7B,MAAM,MAAM,mBAAmB,GAAG,KAAK,GAAG,KAAK,EAAE,GAAG,mBAAmB,EAAE,CAAA;AAEzE,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,SAAS,GAAG,SAAS,CAAA;IAC7B,GAAG,EAAE,MAAM,GAAG,GAAG,EAAE,CAAA;IACnB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,EAAE,GAAG,OAAO,CAAA;CACvC;AAED,MAAM,MAAM,mBAAmB,GAAG,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,EAAE,QAAQ,CAAC,EAAE,SAAS,KAAK,mBAAmB,GAAG,IAAI,CAAA;AAEtI,MAAM,MAAM,iBAAiB,GAAG,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,EAAE,QAAQ,CAAC,EAAE,SAAS,KAAK,mBAAmB,CAAA;AAE7H,MAAM,MAAM,gBAAgB,GAAG;IAC7B,CAAC,GAAG,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,IAAI,CAAC;IACvD,aAAa,CAAC,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,GAAG,MAAM,CAAC;IAE5C,WAAW,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,MAAM,CAAC;CAC7D,CAAA;AAED,MAAM,MAAM,SAAS,GAAG,CAAC,EAAE,EAAE,CAAC,KAAK,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,KAAK,GAAG,KAAK,EAAE,CAAC,EAAE,KAAK,MAAM,CAAA;AAEpF,MAAM,MAAM,gBAAgB,GAAG,CAAC,KAAK,EAAE,KAAK,KAAK,UAAU,GAAG,SAAS,CAAA;AAEvE,MAAM,WAAW,eAAe;IAC9B,IAAI,IAAI,OAAO,CAAC;IAChB,IAAI,IAAI,KAAK,CAAC;IACd,GAAG,IAAI,MAAM,CAAC;CACf;AAED,MAAM,MAAM,UAAU,GAAG,CAAC,KAAK,EAAE,GAAG,KAAK,GAAG,CAAA;AAE5C,MAAM,WAAW,aAAa;IAC5B,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,qBAAqB,CAAC,EAAE,OAAO,CAAA;IAC/B,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,sBAAsB,CAAC,EAAE,OAAO,CAAA;IAChC,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B,IAAI,CAAC,EAAE,UAAU,EAAE,CAAC;IACpB,SAAS,CAAC,EAAE,eAAe,CAAA;CAC5B;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,YAAY,CAAC,EAAE;QAAE,CAAC,QAAQ,EAAE,MAAM,GAAG,mBAAmB,CAAA;KAAE,CAAA;CAC3D"} \ No newline at end of file +{"version":3,"file":"interface.d.ts","sourceRoot":"","sources":["../interface.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/types/lib/bl.d.ts b/types/lib/bl.d.ts index 8f6d3aa..94fd358 100644 --- a/types/lib/bl.d.ts +++ b/types/lib/bl.d.ts @@ -23,4 +23,25 @@ export class Bl { */ toBytes(reset?: boolean | undefined): Uint8Array; } +export class U8Bl { + /** + * @param {Uint8Array} dest + */ + constructor(dest: Uint8Array); + dest: Uint8Array; + /** @type {number} */ + cursor: number; + /** @type {Uint8Array[]} */ + chunks: Uint8Array[]; + reset(): void; + /** + * @param {Uint8Array|number[]} bytes + */ + push(bytes: Uint8Array | number[]): void; + /** + * @param {boolean} [reset] + * @returns {Uint8Array} + */ + toBytes(reset?: boolean | undefined): Uint8Array; +} //# sourceMappingURL=bl.d.ts.map \ No newline at end of file diff --git a/types/lib/bl.d.ts.map b/types/lib/bl.d.ts.map index c80a00d..246d7e5 100644 --- a/types/lib/bl.d.ts.map +++ b/types/lib/bl.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"bl.d.ts","sourceRoot":"","sources":["../../lib/bl.js"],"names":[],"mappings":"AA0BA;IACE;;OAEG;IACH,4CAWC;IAVC,kBAA0B;IAC1B,qBAAqB;IACrB,QADW,MAAM,CACF;IACf,qBAAqB;IACrB,WADW,MAAM,CACE;IACnB,sCAAsC;IACtC,QADW,CAAC,UAAU,GAAC,MAAM,EAAE,CAAC,EAAE,CAClB;IAEhB,uCAAuC;IACvC,iBADW,UAAU,GAAC,MAAM,EAAE,GAAC,IAAI,CACR;IAG7B,cAUC;IAED;;OAEG;IACH,YAFW,UAAU,GAAC,MAAM,EAAE,QAsC7B;IAED;;;OAGG;IACH,sCAFa,UAAU,CAwBtB;CACF"} \ No newline at end of file +{"version":3,"file":"bl.d.ts","sourceRoot":"","sources":["../../lib/bl.js"],"names":[],"mappings":"AA0BA;IACE;;OAEG;IACH,4CAWC;IAVC,kBAA0B;IAC1B,qBAAqB;IACrB,QADW,MAAM,CACF;IACf,qBAAqB;IACrB,WADW,MAAM,CACE;IACnB,sCAAsC;IACtC,QADW,CAAC,UAAU,GAAC,MAAM,EAAE,CAAC,EAAE,CAClB;IAEhB,uCAAuC;IACvC,iBADW,UAAU,GAAC,MAAM,EAAE,GAAC,IAAI,CACR;IAG7B,cAUC;IAED;;OAEG;IACH,YAFW,UAAU,GAAC,MAAM,EAAE,QAsC7B;IAED;;;OAGG;IACH,sCAFa,UAAU,CAwBtB;CACF;AAED;IACE;;OAEG;IACH,kBAFW,UAAU,EAQpB;IALC,iBAAgB;IAChB,qBAAqB;IACrB,QADW,MAAM,CACF;IACf,2BAA2B;IAC3B,QADW,UAAU,EAAE,CACH;IAGtB,cAEC;IAED;;OAEG;IACH,YAFW,UAAU,GAAC,MAAM,EAAE,QAQ7B;IAED;;;OAGG;IACH,sCAFa,UAAU,CAQtB;CACF"} \ No newline at end of file diff --git a/types/lib/encode.d.ts b/types/lib/encode.d.ts index 234890c..3fe2e58 100644 --- a/types/lib/encode.d.ts +++ b/types/lib/encode.d.ts @@ -6,6 +6,7 @@ export type Reference = import('../interface').Reference; export type StrictTypeEncoder = import('../interface').StrictTypeEncoder; export type TokenTypeEncoder = import('../interface').TokenTypeEncoder; export type TokenOrNestedTokens = import('../interface').TokenOrNestedTokens; +export type Bl = import('../interface').Bl; /** * @param {any} obj * @param {EncodeOptions} [options] @@ -23,9 +24,17 @@ export function encode(data: any, options?: import("../interface").EncodeOptions * @param {any} data * @param {TokenTypeEncoder[]} encoders * @param {EncodeOptions} options + * @param {Uint8Array} [destination] * @returns {Uint8Array} */ -export function encodeCustom(data: any, encoders: TokenTypeEncoder[], options: EncodeOptions): Uint8Array; +export function encodeCustom(data: any, encoders: TokenTypeEncoder[], options: EncodeOptions, destination?: Uint8Array | undefined): Uint8Array; +/** + * @param {any} data + * @param {Uint8Array} destination + * @param {EncodeOptions} [options] + * @returns {Uint8Array} + */ +export function encodeInto(data: any, destination: Uint8Array, options?: import("../interface").EncodeOptions | undefined): Uint8Array; /** @implements {Reference} */ export class Ref implements Reference { /** diff --git a/types/lib/encode.d.ts.map b/types/lib/encode.d.ts.map index 9aafff2..3d89767 100644 --- a/types/lib/encode.d.ts.map +++ b/types/lib/encode.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"encode.d.ts","sourceRoot":"","sources":["../../lib/encode.js"],"names":[],"mappings":"AAgCA,oCAAoC;AACpC,oCADc,gBAAgB,EAAE,CAY/B;4BA3BY,OAAO,cAAc,EAAE,aAAa;kCACpC,OAAO,cAAc,EAAE,mBAAmB;wBAC1C,OAAO,cAAc,EAAE,SAAS;gCAChC,OAAO,cAAc,EAAE,iBAAiB;+BACxC,OAAO,cAAc,EAAE,gBAAgB;kCACvC,OAAO,cAAc,EAAE,mBAAmB;AAgQvD;;;;;GAKG;AACH,oCALW,GAAG,wHAGD,mBAAmB,CAgB/B;AA2JD;;;;GAIG;AACH,6BAJW,GAAG,+DAED,UAAU,CAKtB;AAvCD;;;;;GAKG;AACH,mCALW,GAAG,YACH,gBAAgB,EAAE,WAClB,aAAa,GACX,UAAU,CAyBtB;AAjZD,8BAA8B;AAC9B;IAyBE;;;;OAIG;IACH,0BAJW,SAAS,GAAC,SAAS,OACnB,MAAM,GAAC,GAAG,EAAE,GACV,SAAS,CAOrB;IAlCD;;;OAGG;IACH,iBAHW,MAAM,GAAC,GAAG,EAAE,UACZ,SAAS,GAAC,SAAS,EAK7B;IAFC,oBAAc;IACd,qDAAoB;IAGtB;;;OAGG;IACH,cAHW,MAAM,GAAC,GAAG,EAAE,GACV,OAAO,CAWnB;CAaF"} \ No newline at end of file +{"version":3,"file":"encode.d.ts","sourceRoot":"","sources":["../../lib/encode.js"],"names":[],"mappings":"AAiCA,oCAAoC;AACpC,oCADc,gBAAgB,EAAE,CAY/B;4BA5BY,OAAO,cAAc,EAAE,aAAa;kCACpC,OAAO,cAAc,EAAE,mBAAmB;wBAC1C,OAAO,cAAc,EAAE,SAAS;gCAChC,OAAO,cAAc,EAAE,iBAAiB;+BACxC,OAAO,cAAc,EAAE,gBAAgB;kCACvC,OAAO,cAAc,EAAE,mBAAmB;iBAC1C,OAAO,cAAc,EAAE,EAAE;AAgQtC;;;;;GAKG;AACH,oCALW,GAAG,wHAGD,mBAAmB,CAgB/B;AAkKD;;;;GAIG;AACH,6BAJW,GAAG,+DAED,UAAU,CAKtB;AA9CD;;;;;;GAMG;AACH,mCANW,GAAG,YACH,gBAAgB,EAAE,WAClB,aAAa,yCAEX,UAAU,CA+BtB;AAYD;;;;;GAKG;AACH,iCALW,GAAG,eACH,UAAU,+DAER,UAAU,CAKtB;AA7aD,8BAA8B;AAC9B;IAyBE;;;;OAIG;IACH,0BAJW,SAAS,GAAC,SAAS,OACnB,MAAM,GAAC,GAAG,EAAE,GACV,SAAS,CAOrB;IAlCD;;;OAGG;IACH,iBAHW,MAAM,GAAC,GAAG,EAAE,UACZ,SAAS,GAAC,SAAS,EAK7B;IAFC,oBAAc;IACd,qDAAoB;IAGtB;;;OAGG;IACH,cAHW,MAAM,GAAC,GAAG,EAAE,GACV,OAAO,CAWnB;CAaF"} \ No newline at end of file