Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ extensionCodec | ExtensionCodec | `ExtensinCodec.defaultCodec`
maxDepth | number | `100`
initialBufferSize | number | `2048`
sortKeys | boolean | false
forceFloat32 | boolean | false

### `decode(buffer: ArrayLike<number> | ArrayBuffer, options?: DecodeOptions): unknown`

Expand Down
20 changes: 17 additions & 3 deletions src/Encoder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export class Encoder {
readonly maxDepth = DEFAULT_MAX_DEPTH,
readonly initialBufferSize = DEFAULT_INITIAL_BUFFER_SIZE,
readonly sortKeys = false,
readonly forceFloat32 = false,
) {}

encode(object: unknown, depth: number): void {
Expand Down Expand Up @@ -118,8 +119,16 @@ export class Encoder {
}
}
} else {
this.writeU8(0xcb);
this.writeF64(object);
// non-integer numbers
if (this.forceFloat32) {
// float 32
this.writeU8(0xca);
this.writeF32(object);
} else {
// float 64
this.writeU8(0xcb);
this.writeF64(object);
}
}
}

Expand Down Expand Up @@ -345,9 +354,14 @@ export class Encoder {
this.pos += 4;
}

writeF32(value: number) {
this.ensureBufferSizeToWrite(4);
this.view.setFloat32(this.pos, value);
this.pos += 4;
}

writeF64(value: number) {
this.ensureBufferSizeToWrite(8);

this.view.setFloat64(this.pos, value);
this.pos += 8;
}
Expand Down
15 changes: 14 additions & 1 deletion src/encode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@ export type EncodeOptions = Partial<
maxDepth: number;
initialBufferSize: number;
sortKeys: boolean;

/**
* If `true`, non-integer numbers are encoded in float32, not in float64 (the default).
*
* Only use it if precisions don't matter.
*/
forceFloat32: boolean;
}>
>;

Expand All @@ -19,7 +26,13 @@ const defaultEncodeOptions = {};
* The returned buffer is a slice of a larger `ArrayBuffer`, so you have to use its `#byteOffset` and `#byteLength` in order to convert it to another typed arrays including NodeJS `Buffer`.
*/
export function encode(value: unknown, options: EncodeOptions = defaultEncodeOptions): Uint8Array {
const encoder = new Encoder(options.extensionCodec, options.maxDepth, options.initialBufferSize, options.sortKeys);
const encoder = new Encoder(
options.extensionCodec,
options.maxDepth,
options.initialBufferSize,
options.sortKeys,
options.forceFloat32,
);
encoder.encode(value, 1);
return encoder.getUint8Array();
}
19 changes: 18 additions & 1 deletion test/encode.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,28 @@ import { encode, decode } from "@msgpack/msgpack";

describe("encode", () => {
context("sortKeys", () => {
it("canonicalize encoded binaries", () => {
it("canonicalizes encoded binaries", () => {
assert.deepStrictEqual(encode({ a: 1, b: 2 }, { sortKeys: true }), encode({ b: 2, a: 1 }, { sortKeys: true }));
});
});

context("forceFloat32", () => {
it("encodes numbers in float64 wihout forceFloat32", () => {
assert.deepStrictEqual(encode(3.14), Uint8Array.from([0xcb, 0x40, 0x9, 0x1e, 0xb8, 0x51, 0xeb, 0x85, 0x1f]));
});

it("encodes numbers in float32 when forceFloate32=true", () => {
assert.deepStrictEqual(encode(3.14, { forceFloat32: true }), Uint8Array.from([0xca, 0x40, 0x48, 0xf5, 0xc3]));
});

it("encodes numbers in float64 with forceFloat32=false", () => {
assert.deepStrictEqual(
encode(3.14, { forceFloat32: false }),
Uint8Array.from([0xcb, 0x40, 0x9, 0x1e, 0xb8, 0x51, 0xeb, 0x85, 0x1f]),
);
});
});

context("ArrayBuffer as buffer", () => {
const buffer = encode([1, 2, 3]);
const arrayBuffer = buffer.buffer.slice(buffer.byteOffset, buffer.byteLength);
Expand Down