-
Notifications
You must be signed in to change notification settings - Fork 170
/
Copy pathJavaScriptCodec.ts
69 lines (61 loc) · 1.68 KB
/
JavaScriptCodec.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
import { ExtensionCodec, ExtensionCodecType } from "./ExtensionCodec";
import { encode } from "./encode";
import { decode } from "./decode";
export const EXT_JAVASCRIPT = 0;
const enum JSData {
Map,
Set,
Date,
RegExp,
BigInt,
}
export function encodeJavaScriptData(input: unknown): Uint8Array | null {
if (input instanceof Map) {
return encode([JSData.Map, [...input]]);
} else if (input instanceof Set) {
return encode([JSData.Set, [...input]]);
} else if (input instanceof Date) {
// Not a MessagePack timestamp because
// it may be overrided by users
return encode([JSData.Date, input.getTime()]);
} else if (input instanceof RegExp) {
return encode([JSData.RegExp, [input.source, input.flags]]);
} else if (typeof input === "bigint") {
return encode([JSData.BigInt, input.toString()]);
} else {
return null;
}
}
export function decodeJavaScriptData(data: Uint8Array) {
const [jsDataType, source] = decode(data) as [JSData, any];
switch (jsDataType) {
case JSData.Map: {
return new Map<unknown, unknown>(source);
}
case JSData.Set: {
return new Set<unknown>(source);
}
case JSData.Date: {
return new Date(source);
}
case JSData.RegExp: {
const [pattern, flags] = source;
return new RegExp(pattern, flags);
}
case JSData.BigInt: {
return BigInt(source);
}
default: {
throw new Error(`Unknown data type: ${jsDataType}`);
}
}
}
export const JavaScriptCodec: ExtensionCodecType = (() => {
const ext = new ExtensionCodec();
ext.register({
type: EXT_JAVASCRIPT,
encode: encodeJavaScriptData,
decode: decodeJavaScriptData,
});
return ext;
})();