Skip to content

Commit 7327c0d

Browse files
committed
native support for number encode
1 parent 7a9b287 commit 7327c0d

File tree

4 files changed

+92
-89
lines changed

4 files changed

+92
-89
lines changed

src/codec.ts

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -28,23 +28,10 @@ export function decodeBase64(str: string): Uint8Array {
2828
}
2929

3030

31-
export function encodeNumner(self: number): string {
32-
return '͢Number:' + self.toString();
33-
}
34-
35-
export function decodeNumber(str: string): number {
36-
return Number.parseFloat(str.substring(8));
37-
}
38-
3931
export function encodeBigInt(self: BigInt): string {
40-
return '͢BigInt:' + self.toString();
32+
return '͢n:' + self.toString();
4133
}
4234

4335
export function decodeBigInt(str: string): BigInt {
44-
return BigInt(str.substring(8));
36+
return BigInt(str.substring(3));
4537
}
46-
47-
export function encodeBoolean(self: boolean): string {
48-
return '͢' + self.toString();
49-
}
50-

src/index.ts

Lines changed: 58 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
11
import {
2-
decodeBase64,
3-
decodeBigInt,
4-
decodeDate, decodeNumber,
2+
decodeBase64, decodeBigInt,
3+
decodeDate,
54
decodeUint8Array,
6-
encodeBase64,
7-
encodeBigInt, encodeBoolean,
5+
encodeBase64, encodeBigInt,
86
encodeDate,
9-
encodeNumner,
107
encodeUint8Array
118
} from "./codec";
129

@@ -22,18 +19,15 @@ function hasToArrow(obj: unknown): obj is ArrowObject {
2219
}
2320

2421
interface Options {
25-
encodeBinary?: boolean | 'base64';
22+
encodeBinary?: boolean | 'base64'; // default true
2623
encodeDate?: boolean; // default true
27-
encodeBigInt?: boolean; // default true
28-
encodePrimitive?: boolean; // default false
24+
encodeBigInt?: boolean; // default false
2925
}
3026

3127
export default class Arrow {
3228
private _encodeTable: Map<any, (self: object) => string> = new Map();
3329
private _decodeTable: { [key: string]: (str: string) => object } = {};
3430

35-
encodePrimitive = false;
36-
3731
constructor(options?: Options) {
3832
if (options?.encodeBinary === 'base64') {
3933
this.registerRaw('B64', Uint8Array, encodeBase64, decodeBase64);
@@ -47,13 +41,8 @@ export default class Arrow {
4741
if (options?.encodeDate !== false) {
4842
this.registerRaw('Date', Date, encodeDate, decodeDate);
4943
}
50-
if (options?.encodeBigInt !== false) {
51-
this.registerRaw('BigInt', BigInt, encodeBigInt, decodeBigInt);
52-
}
53-
54-
if (options?.encodePrimitive) {
55-
this.encodePrimitive = true;
56-
this.registerRaw('Number', Number, null, decodeNumber);
44+
if (options?.encodeBigInt === true) {
45+
this.registerRaw('n', BigInt, encodeBigInt, decodeBigInt);
5746
}
5847
}
5948

@@ -79,20 +68,14 @@ export default class Arrow {
7968

8069
reviver(key: string, value: unknown): unknown {
8170
if (typeof value === 'string' && value.charCodeAt(0) === 0x362) {
82-
if (value.length < 7) {
71+
if (value.length < 6) {
8372
switch (value) {
8473
case '͢NaN':
8574
return NaN;
8675
case '͢Inf':
8776
return Infinity;
8877
case '͢-Inf':
8978
return -Infinity;
90-
case '͢true':
91-
return true;
92-
case '͢false':
93-
return false;
94-
case '͢null':
95-
return null;
9679
}
9780
}
9881
let colonPos = value.indexOf(':');
@@ -264,23 +247,20 @@ export default class Arrow {
264247

265248
encode(input: unknown): string {
266249
const result = this.replacer(null, input, null);
267-
if (this.encodePrimitive) {
268-
switch (typeof result) {
269-
case "string":
270-
return result;
271-
case "number":
272-
return encodeNumner(input as number);
273-
case "boolean":
274-
return encodeBoolean(input as boolean);
275-
case 'undefined':
276-
return UNDEFINED;
277-
default:
278-
if (result === null) {
279-
return '͢null';
280-
}
281-
}
282-
} else if (typeof result === 'string') {
283-
return result;
250+
switch (typeof result) {
251+
case "string":
252+
return result;
253+
case "number":
254+
return ${input}`;
255+
case "boolean":
256+
return ${input}`;
257+
case 'undefined':
258+
return UNDEFINED;
259+
case "bigint":
260+
return encodeBigInt(input as BigInt);
261+
}
262+
if (result === null) {
263+
return '͢null';
284264
}
285265
if (Array.isArray(input) || input?.constructor === Object) {
286266
return ${this.encodeJSON(input)}`;
@@ -289,10 +269,43 @@ export default class Arrow {
289269
}
290270

291271
decode(str: string): unknown {
292-
if (str.startsWith('͢[') || str.startsWith('͢{')) {
293-
return this.decodeJSON(str.substring(1));
272+
if (typeof str === 'string' && str.charCodeAt(0) === 0x362) {
273+
if (str.length < 7) {
274+
switch (str) {
275+
case '͢NaN':
276+
return NaN;
277+
case '͢Inf':
278+
return Infinity;
279+
case '͢-Inf':
280+
return -Infinity;
281+
case '͢true':
282+
return true;
283+
case '͢false':
284+
return false;
285+
case '͢null':
286+
return null;
287+
case '͢':
288+
return undefined;
289+
}
290+
}
291+
let firstChar = str.charAt(1);
292+
if (firstChar === '[' || firstChar === '{') {
293+
return this.decodeJSON(str.substring(1));
294+
}
295+
if ((firstChar >= '0' && firstChar <= '9') || firstChar === '-') {
296+
return Number.parseFloat(str.substring(1));
297+
}
298+
let colonPos = str.indexOf(':');
299+
if (colonPos > -1) {
300+
let key = str.substring(1, colonPos);
301+
let decoder = this._decodeTable[key];
302+
if (decoder) {
303+
return decoder(str);
304+
}
305+
}
306+
return undefined;
294307
}
295-
return this.reviver(null, str);
308+
return str;
296309
}
297310

298311
encodeJSON(input: unknown, space?: number, sortKeys: boolean = false): string {

test/test-string.ts

Lines changed: 30 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -9,21 +9,18 @@ const undefinedStr = '͢';
99
const trueStr = '͢true';
1010
const falseStr = '͢false';
1111

12-
const arrow = new Arrow({encodePrimitive: true});
13-
1412
describe('string', () => {
1513
it('numbers', () => {
16-
assert.isNaN(arrow.decode(nanStr), 'decode NaN');
17-
assert.isNaN(arrow.decode(nanStr), 'decode NaN');
18-
assert.equal(arrow.decode(infStr), Infinity, 'decode Infinity');
19-
assert.equal(arrow.decode(ninfStr), -Infinity, 'decode -Infinity');
20-
assert.equal(arrow.decode('1.25'), 1.25, 'decode normal value');
21-
assert.equal(arrow.decode('͢Number:1.25'), 1.25, 'decode normal value');
22-
23-
assert.equal(arrow.encode(NaN), nanStr, 'encode NaN');
24-
assert.equal(arrow.encode(Infinity), infStr, 'encode Infinity');
25-
assert.equal(arrow.encode(-Infinity), ninfStr, 'encode -Infinity');
26-
assert.equal(arrow.encode(1.25), '͢Number:1.25', 'encode normal number');
14+
assert.isNaN(Arrow.decode(nanStr), 'decode NaN');
15+
assert.isNaN(Arrow.decode(nanStr), 'decode NaN');
16+
assert.equal(Arrow.decode(infStr), Infinity, 'decode Infinity');
17+
assert.equal(Arrow.decode(ninfStr), -Infinity, 'decode -Infinity');
18+
assert.equal(Arrow.decode('͢1.25'), 1.25, 'decode normal value');
19+
20+
assert.equal(Arrow.encode(NaN), nanStr, 'encode NaN');
21+
assert.equal(Arrow.encode(Infinity), infStr, 'encode Infinity');
22+
assert.equal(Arrow.encode(-Infinity), ninfStr, 'encode -Infinity');
23+
assert.equal(Arrow.encode(1.25), '͢1.25', 'encode normal number');
2724
});
2825

2926
it('Date', () => {
@@ -36,28 +33,34 @@ describe('string', () => {
3633
});
3734

3835
it('bool', () => {
39-
assert.isTrue(arrow.decode(trueStr), 'decode true');
40-
assert.isFalse(arrow.decode(falseStr), 'decode false');
36+
assert.isTrue(Arrow.decode(trueStr), 'decode true');
37+
assert.isFalse(Arrow.decode(falseStr), 'decode false');
4138

42-
assert.equal(arrow.encode(true), trueStr, 'encode true');
43-
assert.equal(arrow.encode(false), falseStr, 'encode false');
44-
assert.equal(arrow.encodeJSON(true), 'true', 'encode JSON true');
45-
assert.equal(arrow.encodeJSON(false), 'false', 'encode JSON false');
39+
assert.equal(Arrow.encode(true), trueStr, 'encode true');
40+
assert.equal(Arrow.encode(false), falseStr, 'encode false');
41+
assert.equal(Arrow.encodeJSON(true), 'true', 'encode JSON true');
42+
assert.equal(Arrow.encodeJSON(false), 'false', 'encode JSON false');
4643
});
4744

4845
it('other', () => {
49-
assert.isNull(arrow.decode(nullStr), 'decode null');
50-
assert.isUndefined(arrow.decode(undefinedStr), 'decode undefined');
46+
assert.isNull(Arrow.decode(nullStr), 'decode null');
47+
assert.isUndefined(Arrow.decode(undefinedStr), 'decode undefined');
5148

52-
assert.equal(arrow.encode(null), nullStr, 'encode null');
53-
assert.equal(arrow.encode(undefined), undefinedStr, 'encode undefined');
49+
assert.equal(Arrow.encode(null), nullStr, 'encode null');
50+
assert.equal(Arrow.encode(undefined), undefinedStr, 'encode undefined');
5451
});
5552

5653
it('object', () => {
57-
assert.deepEqual(arrow.decode('͢{"a":1}'), {a: 1}, 'decode object');
58-
assert.deepEqual(arrow.decode('͢[1,2]'), [1, 2], 'decode array');
54+
assert.deepEqual(Arrow.decode('͢{"a":1}'), {a: 1}, 'decode object');
55+
assert.deepEqual(Arrow.decode('͢[1,2]'), [1, 2], 'decode array');
56+
57+
assert.equal(Arrow.encode({a: 1}), '͢{"a":1}', 'encode object');
58+
assert.equal(Arrow.encode([1, 2]), '͢[1,2]', 'encode array');
59+
});
60+
61+
it('BigInt', () => {
62+
assert.equal(Arrow.decode('͢n:1'), 1n, 'decode BigInt');
5963

60-
assert.equal(arrow.encode({a: 1}), '͢{"a":1}', 'encode object');
61-
assert.equal(arrow.encode([1, 2]), '͢[1,2]', 'encode array');
64+
assert.equal(Arrow.encode(2n), '͢n:2', 'encode BigInt');
6265
});
6366
});

tsconfig.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
{
22
"compilerOptions": {
3-
"target": "es2017",
3+
"target": "es2020",
44
"module": "none",
55
"moduleResolution": "node",
66
"lib": [
7-
"es2017"
7+
"es2020"
88
],
99
"alwaysStrict": true,
1010
"noImplicitAny": true,

0 commit comments

Comments
 (0)