-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add encodedLength() function (#48)
- Loading branch information
Showing
13 changed files
with
211 additions
and
30 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
import { makeCborEncoders, objectToTokens } from './encode.js' | ||
import { quickEncodeToken } from './jump.js' | ||
|
||
/** | ||
* @typedef {import('../interface').EncodeOptions} EncodeOptions | ||
* @typedef {import('../interface').TokenTypeEncoder} TokenTypeEncoder | ||
* @typedef {import('../interface').TokenOrNestedTokens} TokenOrNestedTokens | ||
*/ | ||
|
||
const cborEncoders = makeCborEncoders() | ||
|
||
/** @type {EncodeOptions} */ | ||
const defaultEncodeOptions = { | ||
float64: false, | ||
quickEncodeToken | ||
} | ||
|
||
/** | ||
* Calculate the byte length of the given data when encoded as CBOR with the | ||
* options provided. | ||
* This calculation will be accurate if the same options are used as when | ||
* performing a normal encode. Some encode options can change the encoding | ||
* output length. | ||
* | ||
* @param {any} data | ||
* @param {EncodeOptions} [options] | ||
* @returns {number} | ||
*/ | ||
export function encodedLength (data, options) { | ||
options = Object.assign({}, defaultEncodeOptions, options) | ||
options.mapSorter = undefined // won't change the length | ||
const tokens = objectToTokens(data, options) | ||
return tokensToLength(tokens, cborEncoders, options) | ||
} | ||
|
||
/** | ||
* Calculate the byte length of the data as represented by the given tokens when | ||
* encoded as CBOR with the options provided. | ||
* This function is for advanced users and would not normally be called | ||
* directly. See `encodedLength()` for appropriate use. | ||
* | ||
* @param {TokenOrNestedTokens} tokens | ||
* @param {TokenTypeEncoder[]} [encoders] | ||
* @param {EncodeOptions} [options] | ||
*/ | ||
export function tokensToLength (tokens, encoders = cborEncoders, options = defaultEncodeOptions) { | ||
if (Array.isArray(tokens)) { | ||
let len = 0 | ||
for (const token of tokens) { | ||
len += tokensToLength(token, encoders, options) | ||
} | ||
return len | ||
} else { | ||
const encoder = encoders[tokens.type.major] | ||
/* c8 ignore next 3 */ | ||
if (encoder.encodedSize === undefined || typeof encoder.encodedSize !== 'function') { | ||
throw new Error(`Encoder for ${tokens.type.name} does not have an encodedSize()`) | ||
} | ||
return encoder.encodedSize(tokens, options) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import { Token, Type } from '../lib/token.js' | ||
|
||
export function dateDecoder (obj) { | ||
if (typeof obj !== 'string') { | ||
throw new Error('expected string for tag 1') | ||
} | ||
return new Date(obj) | ||
} | ||
|
||
export function dateEncoder (obj) { | ||
if (!(obj instanceof Date)) { | ||
throw new Error('expected Date for "Date" encoder') | ||
} | ||
return [ | ||
new Token(Type.tag, 0), | ||
new Token(Type.string, obj.toISOString().replace(/\.000Z$/, 'Z')) | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
/* eslint-env mocha */ | ||
|
||
import chai from 'chai' | ||
import { garbage } from 'ipld-garbage' | ||
import { uintBoundaries } from '../lib/0uint.js' | ||
import { encode } from '../cborg.js' | ||
import { encodedLength } from '../lib/length.js' | ||
import { dateEncoder } from './common.js' | ||
|
||
const { assert } = chai | ||
|
||
function verifyLength (object, options) { | ||
const len = encodedLength(object, options) | ||
const encoded = encode(object, options) | ||
const actual = encoded.length | ||
assert.strictEqual(actual, len, JSON.stringify(object)) | ||
} | ||
|
||
describe('encodedLength', () => { | ||
it('int boundaries', () => { | ||
for (let ii = 0; ii < 4; ii++) { | ||
verifyLength(uintBoundaries[ii]) | ||
verifyLength(uintBoundaries[ii] - 1) | ||
verifyLength(uintBoundaries[ii] + 1) | ||
verifyLength(-1 * uintBoundaries[ii]) | ||
verifyLength(-1 * uintBoundaries[ii] - 1) | ||
verifyLength(-1 * uintBoundaries[ii] + 1) | ||
} | ||
}) | ||
|
||
it('tags', () => { | ||
verifyLength({ date: new Date('2013-03-21T20:04:00Z') }, { typeEncoders: { Date: dateEncoder } }) | ||
}) | ||
|
||
it('floats', () => { | ||
verifyLength(0.5) | ||
verifyLength(0.5, { float64: true }) | ||
verifyLength(8.940696716308594e-08) | ||
verifyLength(8.940696716308594e-08, { float64: true }) | ||
}) | ||
|
||
it('small garbage', function () { | ||
this.timeout(10000) | ||
for (let ii = 0; ii < 1000; ii++) { | ||
const gbg = garbage(1 << 6, { weights: { CID: 0 } }) | ||
verifyLength(gbg) | ||
} | ||
}) | ||
|
||
it('medium garbage', function () { | ||
this.timeout(10000) | ||
for (let ii = 0; ii < 100; ii++) { | ||
const gbg = garbage(1 << 16, { weights: { CID: 0 } }) | ||
verifyLength(gbg) | ||
} | ||
}) | ||
|
||
it('large garbage', function () { | ||
this.timeout(10000) | ||
for (let ii = 0; ii < 10; ii++) { | ||
const gbg = garbage(1 << 20, { weights: { CID: 0 } }) | ||
verifyLength(gbg) | ||
} | ||
}) | ||
}) |