-
-
Notifications
You must be signed in to change notification settings - Fork 286
/
MsgPack.js
56 lines (50 loc) · 2.75 KB
/
MsgPack.js
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
// ES6 import for msgpack-lite, we use the fonsp/msgpack-lite fork to make it ES6-importable (without nodejs)
import msgpack from "../imports/msgpack-lite.js"
// based on https://github.com/kawanet/msgpack-lite/blob/5b71d82cad4b96289a466a6403d2faaa3e254167/lib/ext-packer.js
const codec = msgpack.createCodec()
const packTypedArray = (x) => new Uint8Array(x.buffer)
codec.addExtPacker(0x11, Int8Array, packTypedArray)
codec.addExtPacker(0x12, Uint8Array, packTypedArray)
codec.addExtPacker(0x13, Int16Array, packTypedArray)
codec.addExtPacker(0x14, Uint16Array, packTypedArray)
codec.addExtPacker(0x15, Int32Array, packTypedArray)
codec.addExtPacker(0x16, Uint32Array, packTypedArray)
codec.addExtPacker(0x17, Float32Array, packTypedArray)
codec.addExtPacker(0x18, Float64Array, packTypedArray)
codec.addExtPacker(0x12, Uint8ClampedArray, packTypedArray)
codec.addExtPacker(0x12, ArrayBuffer, (x) => new Uint8Array(x))
codec.addExtPacker(0x12, DataView, packTypedArray)
// Pack and unpack dates. However, encoding a date does throw on Safari because it doesn't have BigInt64Array.
// This isn't too much a problem, as Safari doesn't even support <input type=date /> yet...
// But it does throw when I create a custom @bind that has a Date value...
// For decoding I now also use a "Invalid Date", but the code in https://stackoverflow.com/a/55338384/2681964 did work in Safari.
// Also there is no way now to send an "Invalid Date", so it just does nothing
codec.addExtPacker(0x0d, Date, (d) => new BigInt64Array([BigInt(d)]))
codec.addExtUnpacker(0x0d, (uintarray) => {
if ("getBigInt64" in DataView.prototype) {
let dataview = new DataView(uintarray.buffer, uintarray.byteOffset, uintarray.byteLength)
let bigint = dataview.getBigInt64(0, true) // true here is "littleEndianes", not sure if this only Works On My Machine©
if (bigint > Number.MAX_SAFE_INTEGER) {
throw new Error(`Can't read too big number as date (how far in the future is this?!)`)
}
return new Date(Number(bigint))
} else {
return new Date(NaN)
}
})
codec.addExtUnpacker(0x11, (buffer) => new Int8Array(buffer))
codec.addExtUnpacker(0x12, (buffer) => new Uint8Array(buffer))
codec.addExtUnpacker(0x13, (buffer) => new Int16Array(buffer))
codec.addExtUnpacker(0x14, (buffer) => new Uint16Array(buffer))
codec.addExtUnpacker(0x15, (buffer) => new Int32Array(buffer))
codec.addExtUnpacker(0x16, (buffer) => new Uint32Array(buffer))
codec.addExtUnpacker(0x17, (buffer) => new Float32Array(buffer))
codec.addExtUnpacker(0x18, (buffer) => new Float64Array(buffer))
/** @param {any} x */
export const pack = (x) => {
return msgpack.encode(x, { codec: codec })
}
/** @param {Uint8Array} x */
export const unpack = (x) => {
return msgpack.decode(x, { codec: codec })
}