Skip to content

Commit b026b7d

Browse files
authored
revert msgpackr (#351)
## Why the deserialization of the 'bin' type is different across msgpackr and @msgpack/msgpack :( see also: kriszyp/msgpackr#175 ## What changed go back to @msgpack/msgpack for now ## Versioning - [ ] Breaking protocol change - [ ] Breaking ts/js API change <!-- Kind reminder to add tests and updated documentation if needed -->
1 parent b2d7454 commit b026b7d

File tree

4 files changed

+991
-474
lines changed

4 files changed

+991
-474
lines changed

codec/binary.ts

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,48 @@
1-
import { Options, Packr } from 'msgpackr';
1+
import { DecodeError, ExtensionCodec, decode, encode } from '@msgpack/msgpack';
22
import { Codec } from './types';
33

4-
const packr = new Packr({
5-
useRecords: false,
6-
moreTypes: true,
7-
bundleStrings: true,
8-
useTimestamp32: false,
9-
useBigIntExtension: true,
10-
skipValues: [undefined],
11-
} as Options);
4+
const BIGINT_EXT_TYPE = 0;
5+
const extensionCodec = new ExtensionCodec();
6+
extensionCodec.register({
7+
type: BIGINT_EXT_TYPE,
8+
encode(input: unknown): Uint8Array | null {
9+
if (typeof input === 'bigint') {
10+
if (
11+
input <= Number.MAX_SAFE_INTEGER &&
12+
input >= Number.MIN_SAFE_INTEGER
13+
) {
14+
return encode(Number(input));
15+
} else {
16+
return encode(String(input));
17+
}
18+
} else {
19+
return null;
20+
}
21+
},
22+
decode(data: Uint8Array): bigint {
23+
const val = decode(data);
24+
if (!(typeof val === 'string' || typeof val === 'number')) {
25+
throw new DecodeError(`unexpected BigInt source: ${typeof val}`);
26+
}
27+
28+
return BigInt(val);
29+
},
30+
});
1231

1332
/**
14-
* Binary codec, uses [msgpackr](https://www.npmjs.com/package/msgpackr) under the hood
33+
* Binary codec, uses [msgpack](https://www.npmjs.com/package/@msgpack/msgpack) under the hood
1534
* @type {Codec}
1635
*/
1736
export const BinaryCodec: Codec = {
1837
toBuffer(obj) {
19-
return packr.pack(obj);
38+
return encode(obj, {
39+
ignoreUndefined: true,
40+
initialBufferSize: 512,
41+
extensionCodec,
42+
});
2043
},
2144
fromBuffer: (buff: Uint8Array) => {
22-
const res: unknown = packr.unpack(buff);
45+
const res = decode(buff, { extensionCodec });
2346
if (typeof res !== 'object' || res === null) {
2447
throw new Error('unpacked msg is not an object');
2548
}

codec/codec.test.ts

Lines changed: 34 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,47 @@
11
import { describe, test, expect } from 'vitest';
22
import { codecs } from '../testUtil/fixtures/codec';
33

4-
describe.each(codecs)('codec -- $name', ({ codec }) => {
5-
test('empty object', () => {
6-
const msg = {};
7-
expect(codec.fromBuffer(codec.toBuffer(msg))).toStrictEqual(msg);
8-
});
9-
10-
test('simple test', () => {
11-
const msg = { abc: 123, def: 'cool' };
12-
expect(codec.fromBuffer(codec.toBuffer(msg))).toStrictEqual(msg);
13-
});
14-
15-
test('encodes null properly', () => {
16-
const msg = { test: null };
17-
expect(codec.fromBuffer(codec.toBuffer(msg))).toStrictEqual(msg);
18-
});
19-
20-
test('encodes the empty buffer properly', () => {
21-
const msg = { test: new Uint8Array(0) };
22-
expect(codec.fromBuffer(codec.toBuffer(msg))).toStrictEqual(msg);
23-
});
24-
25-
test('skips optional fields', () => {
26-
const msg = { test: undefined };
27-
expect(codec.fromBuffer(codec.toBuffer(msg))).toStrictEqual({});
28-
});
29-
30-
test('encodes bigint properly', () => {
31-
const msg = { big: BigInt(Number.MAX_SAFE_INTEGER) + BigInt(1) };
32-
expect(codec.fromBuffer(codec.toBuffer(msg))).toStrictEqual(msg);
33-
});
34-
35-
test('deeply nested test', () => {
36-
const msg = {
4+
const examples: Array<{
5+
name: string;
6+
obj: Record<string, unknown>;
7+
expected?: Record<string, unknown>;
8+
}> = [
9+
{ name: 'empty object', obj: {} },
10+
{ name: 'simple object', obj: { abc: 123, def: 'cool' } },
11+
{ name: 'non-utf8 string', obj: { test: '🇧🇪你好世界' } },
12+
{ name: 'null value', obj: { test: null } },
13+
{ name: 'empty buffer', obj: { test: new Uint8Array(0) } },
14+
{ name: 'optional field', obj: { test: undefined }, expected: {} },
15+
{
16+
name: 'bigint value',
17+
obj: { big: BigInt(Number.MAX_SAFE_INTEGER) + BigInt(1) },
18+
},
19+
{
20+
name: 'deeply nested',
21+
obj: {
3722
array: [{ object: true }],
3823
deeply: {
3924
nested: {
4025
nice: null,
4126
},
4227
},
43-
};
44-
expect(codec.fromBuffer(codec.toBuffer(msg))).toStrictEqual(msg);
45-
});
46-
47-
test('buffer test', () => {
48-
const msg = {
28+
},
29+
},
30+
{
31+
name: 'buffer test',
32+
obj: {
4933
buff: Uint8Array.from([0, 42, 100, 255]),
50-
};
51-
expect(codec.fromBuffer(codec.toBuffer(msg))).toStrictEqual(msg);
34+
},
35+
},
36+
];
37+
38+
describe.each(codecs)('codec -- $name', ({ codec }) => {
39+
describe.each(examples)('example -- $name', ({ obj, expected }) => {
40+
test('encodes and decodes correctly', () => {
41+
expect(codec.fromBuffer(codec.toBuffer(obj))).toStrictEqual(
42+
expected ?? obj,
43+
);
44+
});
5245
});
5346

5447
test('invalid json throws', () => {

0 commit comments

Comments
 (0)