-
Notifications
You must be signed in to change notification settings - Fork 2
/
serializers.ts
105 lines (91 loc) · 2.57 KB
/
serializers.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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
import type { Message, MessageSerializer } from "./channel.ts";
import { ensureChunked } from "./server.ts";
export const jsonSerializer = <TSend, TReceive>(): MessageSerializer<
TSend,
TReceive,
string
> => {
return {
deserialize: (msg) => {
const parsed = JSON.parse(msg);
if (!("chunk" in parsed)) {
return parsed;
}
const { chunk, ...rest } = parsed;
return {
chunk: ensureChunked(chunk),
...rest,
};
},
serialize: JSON.stringify,
};
};
// Function to combine metadata and binary data
function createMessage(
metadata: unknown,
uint8Array?: Uint8Array,
): ArrayBuffer {
const metadataString = JSON.stringify(metadata);
const metadataUint8Array = new TextEncoder().encode(metadataString);
// Create a buffer to hold the metadata length, metadata, and binary data
const buffer = new ArrayBuffer(
4 + metadataUint8Array.length + (uint8Array?.length ?? 0),
);
const view = new DataView(buffer);
// Write the metadata length (4 bytes)
view.setUint32(0, metadataUint8Array.length, true);
// Write the metadata
new Uint8Array(buffer, 4, metadataUint8Array.length).set(metadataUint8Array);
// Write the binary data
uint8Array &&
new Uint8Array(buffer, 4 + metadataUint8Array.length).set(uint8Array);
return buffer;
}
function parseMessage(
buffer: ArrayBuffer,
// deno-lint-ignore no-explicit-any
): { metadata: any; binaryData: Uint8Array } {
const view = new DataView(buffer);
// Read the metadata length (4 bytes)
const metadataLength = view.getUint32(0, true);
// Read the metadata
const metadataUint8Array = new Uint8Array(buffer, 4, metadataLength);
const metadataString = new TextDecoder().decode(metadataUint8Array);
const metadata = JSON.parse(metadataString);
// Read the binary data
const binaryData = new Uint8Array(buffer, 4 + metadataLength);
return { metadata, binaryData };
}
export const arrayBufferSerializer = (): MessageSerializer<
ArrayBuffer,
ArrayBuffer,
ArrayBuffer
> => {
return {
binaryType: "arraybuffer",
serialize: (msg) => msg,
deserialize: (msg) => msg,
};
};
export const dataViewerSerializer = <
TSend,
TReceive,
>(): MessageSerializer<
TSend,
TReceive,
ArrayBuffer
> => {
return {
binaryType: "arraybuffer",
serialize: ({ chunk, ...rest }: Message<TSend>) => {
return createMessage(rest, chunk);
},
deserialize: (buffer: ArrayBuffer) => {
const parsed = parseMessage(buffer);
return {
...parsed.metadata,
chunk: parsed.binaryData,
};
},
};
};