dredless 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/README.md +48 -48
  2. package/docs/API_REFERENCE.md +2481 -2481
  3. package/docs/BROWSER_API.md +98 -98
  4. package/docs/NODE_API.md +359 -359
  5. package/package.json +34 -34
  6. package/src/browser.d.ts +212 -212
  7. package/src/browser.js +133 -133
  8. package/src/client/core.js +1202 -1202
  9. package/src/client/domains/index.js +1818 -1818
  10. package/src/client/index.d.ts +2 -2
  11. package/src/client/index.js +1 -1
  12. package/src/compression/lz4.d.ts +1 -1
  13. package/src/compression/lz4.js +112 -112
  14. package/src/constants.js +74 -74
  15. package/src/crypto/chacha-native.d.ts +9 -9
  16. package/src/crypto/chacha-native.js +48 -48
  17. package/src/crypto/chacha.d.ts +25 -25
  18. package/src/crypto/chacha.js +274 -274
  19. package/src/events.js +39 -39
  20. package/src/index.d.ts +2277 -2277
  21. package/src/index.js +125 -125
  22. package/src/network/browser-session.js +291 -291
  23. package/src/network/connection.d.ts +1 -1
  24. package/src/network/connection.js +31 -31
  25. package/src/network/cookies.js +85 -85
  26. package/src/network/http.js +34 -34
  27. package/src/network/index.d.ts +4 -4
  28. package/src/network/index.js +4 -4
  29. package/src/network/servers.d.ts +7 -7
  30. package/src/network/servers.js +133 -133
  31. package/src/network/session.d.ts +7 -7
  32. package/src/network/session.js +320 -320
  33. package/src/network/ships.d.ts +12 -12
  34. package/src/network/ships.js +73 -73
  35. package/src/node.d.ts +2 -2
  36. package/src/node.js +8 -8
  37. package/src/protocol/codec/binary.d.ts +3 -3
  38. package/src/protocol/codec/binary.js +52 -52
  39. package/src/protocol/codec/msgpack.d.ts +3 -3
  40. package/src/protocol/codec/msgpack.js +555 -555
  41. package/src/protocol/inbound/frame.d.ts +1 -1
  42. package/src/protocol/inbound/frame.js +8 -8
  43. package/src/protocol/inbound/world-payload.d.ts +3 -3
  44. package/src/protocol/inbound/world-payload.js +21 -21
  45. package/src/protocol/index.d.ts +11 -11
  46. package/src/protocol/index.js +19 -19
  47. package/src/protocol/outbound/blueprint.d.ts +22 -22
  48. package/src/protocol/outbound/blueprint.js +36 -36
  49. package/src/protocol/outbound/commands.d.ts +3 -3
  50. package/src/protocol/outbound/commands.js +149 -149
  51. package/src/protocol/outbound/comms.d.ts +28 -28
  52. package/src/protocol/outbound/comms.js +40 -40
  53. package/src/protocol/outbound/inventory.d.ts +64 -64
  54. package/src/protocol/outbound/inventory.js +147 -147
  55. package/src/protocol/outbound/ship-management.d.ts +84 -84
  56. package/src/protocol/outbound/ship-management.js +221 -221
  57. package/src/protocol/outbound/sign.d.ts +18 -18
  58. package/src/protocol/outbound/sign.js +45 -45
  59. package/src/protocol/outbound/ui-config.d.ts +157 -157
  60. package/src/protocol/outbound/ui-config.js +578 -578
  61. package/src/runtime.js +36 -36
  62. package/src/state/generator-maze.d.ts +32 -32
  63. package/src/state/generator-maze.js +370 -370
  64. package/src/state/index.d.ts +3 -3
  65. package/src/state/index.js +3 -3
  66. package/src/state/items.js +20 -20
  67. package/src/state/model/decoder.js +1554 -1554
  68. package/src/state/model/index.d.ts +33 -33
  69. package/src/state/model/index.js +2 -2
  70. package/src/state/model/loader-config.js +1020 -1020
  71. package/src/state/model/reader.js +69 -69
  72. package/src/state/model/state.js +1257 -1257
  73. package/src/state/overworld.js +72 -72
  74. package/src/state/tilesets.js +53 -53
  75. package/src/state/world/index.d.ts +29 -29
  76. package/src/state/world/index.js +180 -180
  77. package/src/state/world/state.js +297 -297
@@ -1,555 +1,555 @@
1
- import {COMMAND_DEFAULT_FORMATS, COMMAND_FIELDS, decoder, encoder} from "../../constants.js";
2
- import {concatBytes, toUint8Array, valuesEqual} from "./binary.js";
3
-
4
- function cloneDragValue(drag) {
5
- if (!drag || typeof drag !== "object") return null;
6
- return {
7
- source: Number(drag.source),
8
- target: Number(drag.target),
9
- split: Boolean(drag.split)
10
- };
11
- }
12
-
13
- function cloneCommand(command) {
14
- const out = {};
15
- for (const key of COMMAND_FIELDS) {
16
- out[key] = key === "drag" ? cloneDragValue(command[key]) : command[key];
17
- }
18
- return out;
19
- }
20
-
21
- function encodeStringBytes(text) {
22
- const bytes = encoder.encode(String(text));
23
- const length = bytes.length;
24
- if (length <= 31) {
25
- const out = new Uint8Array(1 + length);
26
- out[0] = 0xa0 | length;
27
- out.set(bytes, 1);
28
- return out;
29
- }
30
- if (length <= 0xff) {
31
- const out = new Uint8Array(2 + length);
32
- out[0] = 0xd9;
33
- out[1] = length;
34
- out.set(bytes, 2);
35
- return out;
36
- }
37
- const out = new Uint8Array(3 + length);
38
- out[0] = 0xda;
39
- out[1] = (length >>> 8) & 0xff;
40
- out[2] = length & 0xff;
41
- out.set(bytes, 3);
42
- return out;
43
- }
44
-
45
- function encodeNumberWithFormat(value, format) {
46
- const number = Number(value);
47
- switch (format) {
48
- case "positive-fixint":
49
- return Uint8Array.of(number & 0x7f);
50
- case "negative-fixint":
51
- return Uint8Array.of(number & 0xff);
52
- case "uint8":
53
- return Uint8Array.of(0xcc, number & 0xff);
54
- case "uint16":
55
- return Uint8Array.of(0xcd, (number >>> 8) & 0xff, number & 0xff);
56
- case "uint32":
57
- return Uint8Array.of(0xce, (number >>> 24) & 0xff, (number >>> 16) & 0xff, (number >>> 8) & 0xff, number & 0xff);
58
- case "int8":
59
- return Uint8Array.of(0xd0, number & 0xff);
60
- case "int16":
61
- return Uint8Array.of(0xd1, (number >> 8) & 0xff, number & 0xff);
62
- case "int32":
63
- return Uint8Array.of(0xd2, (number >> 24) & 0xff, (number >> 16) & 0xff, (number >> 8) & 0xff, number & 0xff);
64
- case "float64": {
65
- const out = new Uint8Array(9);
66
- out[0] = 0xcb;
67
- new DataView(out.buffer).setFloat64(1, number, false);
68
- return out;
69
- }
70
- case "float32":
71
- default: {
72
- const out = new Uint8Array(5);
73
- out[0] = 0xca;
74
- new DataView(out.buffer).setFloat32(1, number, false);
75
- return out;
76
- }
77
- }
78
- }
79
-
80
- function encodeMapHeader(length, originalHeaderBytes = null) {
81
- if (originalHeaderBytes && originalHeaderBytes.length > 0) return originalHeaderBytes;
82
- if (length <= 15) return Uint8Array.of(0x80 | length);
83
- return Uint8Array.of(0xde, (length >>> 8) & 0xff, length & 0xff);
84
- }
85
-
86
- function encodeValue(key, value, entry) {
87
- if (entry && valuesEqual(value, entry.valueNode.value)) return entry.valueNode.raw;
88
- if (value == null) return Uint8Array.of(0xc0);
89
- if (typeof value === "boolean") return Uint8Array.of(value ? 0xc3 : 0xc2);
90
- if (typeof value === "number") {
91
- const schemaFormat = COMMAND_DEFAULT_FORMATS[key];
92
- let format = schemaFormat && schemaFormat !== "nil" ? schemaFormat : null;
93
- if (!format) {
94
- if (!Number.isInteger(value)) format = "float32";
95
- else if (value >= 0) {
96
- if (value <= 0x7f) format = "positive-fixint";
97
- else if (value <= 0xff) format = "uint8";
98
- else if (value <= 0xffff) format = "uint16";
99
- else format = "uint32";
100
- } else if (value >= -32) format = "negative-fixint";
101
- else if (value >= -128) format = "int8";
102
- else if (value >= -32768) format = "int16";
103
- else format = "int32";
104
- }
105
- return encodeNumberWithFormat(value, format);
106
- }
107
- if (typeof value === "string") return encodeStringBytes(value);
108
- if (key === "drag" && typeof value === "object") {
109
- const sourceEntry = entry?.valueNode?.entries?.find((item) => String(item.key) === "source")?.valueNode;
110
- const targetEntry = entry?.valueNode?.entries?.find((item) => String(item.key) === "target")?.valueNode;
111
- return concatBytes([
112
- Uint8Array.of(0x83),
113
- encodeStringBytes("source"),
114
- encodeNumberWithFormat(Number(value.source || 0), sourceEntry?.format || "positive-fixint"),
115
- encodeStringBytes("target"),
116
- encodeNumberWithFormat(Number(value.target || 0), targetEntry?.format || "positive-fixint"),
117
- encodeStringBytes("split"),
118
- Uint8Array.of(Boolean(value.split) ? 0xc3 : 0xc2)
119
- ]);
120
- }
121
- throw new Error(`Unsupported command field "${key}"`);
122
- }
123
-
124
- function decodeValue(bytes, offset = 0) {
125
- const head = bytes[offset++];
126
- if (head <= 0x7f) return {value: head, format: "positive-fixint", offset, raw: bytes.slice(offset - 1, offset)};
127
- if (head >= 0xe0) return {
128
- value: (head << 24) >> 24,
129
- format: "negative-fixint",
130
- offset,
131
- raw: bytes.slice(offset - 1, offset)
132
- };
133
- if ((head & 0xf0) === 0x80) {
134
- const count = head & 0x0f;
135
- const entries = [];
136
- const obj = {};
137
- for (let i = 0; i < count; i++) {
138
- const keyNode = decodeValue(bytes, offset);
139
- offset = keyNode.offset;
140
- const valueNode = decodeValue(bytes, offset);
141
- offset = valueNode.offset;
142
- entries.push({key: keyNode.value, keyNode, valueNode});
143
- obj[String(keyNode.value)] = valueNode.value;
144
- }
145
- return {
146
- value: obj,
147
- format: "fixmap",
148
- entries,
149
- headerBytes: bytes.slice(offset - 1 - (count * 2), offset),
150
- offset,
151
- raw: bytes.slice(offset - (offset - (offset - 1)), offset)
152
- };
153
- }
154
- if ((head & 0xf0) === 0x90) {
155
- const count = head & 0x0f;
156
- const items = [];
157
- for (let i = 0; i < count; i++) {
158
- const item = decodeValue(bytes, offset);
159
- offset = item.offset;
160
- items.push(item);
161
- }
162
- return {value: items.map((item) => item.value), format: "fixarray", items, offset, raw: bytes.slice(0, offset)};
163
- }
164
- if ((head & 0xe0) === 0xa0) {
165
- const len = head & 0x1f;
166
- const start = offset;
167
- const end = start + len;
168
- return {
169
- value: decoder.decode(bytes.slice(start, end)),
170
- format: "fixstr",
171
- offset: end,
172
- raw: bytes.slice(offset - 1, end)
173
- };
174
- }
175
- switch (head) {
176
- case 0xc0:
177
- return {value: null, format: "nil", offset, raw: bytes.slice(offset - 1, offset)};
178
- case 0xc2:
179
- return {value: false, format: "bool", offset, raw: bytes.slice(offset - 1, offset)};
180
- case 0xc3:
181
- return {value: true, format: "bool", offset, raw: bytes.slice(offset - 1, offset)};
182
- case 0xc4: {
183
- const len = bytes[offset++];
184
- const start = offset;
185
- const end = start + len;
186
- return {value: bytes.slice(start, end), format: "bin8", offset: end, raw: bytes.slice(start - 2, end)};
187
- }
188
- case 0xc5: {
189
- const len = (bytes[offset] << 8) | bytes[offset + 1];
190
- offset += 2;
191
- const start = offset;
192
- const end = start + len;
193
- return {value: bytes.slice(start, end), format: "bin16", offset: end, raw: bytes.slice(start - 3, end)};
194
- }
195
- case 0xc6: {
196
- const len = (bytes[offset] * 0x1000000) + ((bytes[offset + 1] << 16) | (bytes[offset + 2] << 8) | bytes[offset + 3]);
197
- offset += 4;
198
- const start = offset;
199
- const end = start + len;
200
- return {value: bytes.slice(start, end), format: "bin32", offset: end, raw: bytes.slice(start - 5, end)};
201
- }
202
- case 0xca:
203
- return {
204
- value: new DataView(bytes.buffer, bytes.byteOffset + offset, 4).getFloat32(0, false),
205
- format: "float32",
206
- offset: offset + 4,
207
- raw: bytes.slice(offset - 1, offset + 4)
208
- };
209
- case 0xcb:
210
- return {
211
- value: new DataView(bytes.buffer, bytes.byteOffset + offset, 8).getFloat64(0, false),
212
- format: "float64",
213
- offset: offset + 8,
214
- raw: bytes.slice(offset - 1, offset + 8)
215
- };
216
- case 0xcc:
217
- return {
218
- value: bytes[offset],
219
- format: "uint8",
220
- offset: offset + 1,
221
- raw: bytes.slice(offset - 1, offset + 1)
222
- };
223
- case 0xcd:
224
- return {
225
- value: (bytes[offset] << 8) | bytes[offset + 1],
226
- format: "uint16",
227
- offset: offset + 2,
228
- raw: bytes.slice(offset - 1, offset + 2)
229
- };
230
- case 0xce:
231
- return {
232
- value: (((bytes[offset] * 0x1000000) + ((bytes[offset + 1] << 16) | (bytes[offset + 2] << 8) | bytes[offset + 3])) >>> 0),
233
- format: "uint32",
234
- offset: offset + 4,
235
- raw: bytes.slice(offset - 1, offset + 4)
236
- };
237
- case 0xd0:
238
- return {
239
- value: (bytes[offset] << 24) >> 24,
240
- format: "int8",
241
- offset: offset + 1,
242
- raw: bytes.slice(offset - 1, offset + 1)
243
- };
244
- case 0xd1:
245
- return {
246
- value: new DataView(bytes.buffer, bytes.byteOffset + offset, 2).getInt16(0, false),
247
- format: "int16",
248
- offset: offset + 2,
249
- raw: bytes.slice(offset - 1, offset + 2)
250
- };
251
- case 0xd2:
252
- return {
253
- value: new DataView(bytes.buffer, bytes.byteOffset + offset, 4).getInt32(0, false),
254
- format: "int32",
255
- offset: offset + 4,
256
- raw: bytes.slice(offset - 1, offset + 4)
257
- };
258
- case 0xd9: {
259
- const len = bytes[offset++];
260
- const start = offset;
261
- const end = start + len;
262
- return {
263
- value: decoder.decode(bytes.slice(start, end)),
264
- format: "str8",
265
- offset: end,
266
- raw: bytes.slice(start - 2, end)
267
- };
268
- }
269
- case 0xda: {
270
- const len = (bytes[offset] << 8) | bytes[offset + 1];
271
- offset += 2;
272
- const start = offset;
273
- const end = start + len;
274
- return {
275
- value: decoder.decode(bytes.slice(start, end)),
276
- format: "str16",
277
- offset: end,
278
- raw: bytes.slice(start - 3, end)
279
- };
280
- }
281
- case 0xdc: {
282
- const count = (bytes[offset] << 8) | bytes[offset + 1];
283
- offset += 2;
284
- const items = [];
285
- for (let i = 0; i < count; i++) {
286
- const item = decodeValue(bytes, offset);
287
- offset = item.offset;
288
- items.push(item);
289
- }
290
- return {
291
- value: items.map((item) => item.value),
292
- format: "array16",
293
- items,
294
- offset,
295
- raw: bytes.slice(0, offset)
296
- };
297
- }
298
- case 0xde: {
299
- const count = (bytes[offset] << 8) | bytes[offset + 1];
300
- offset += 2;
301
- const entries = [];
302
- const obj = {};
303
- for (let i = 0; i < count; i++) {
304
- const keyNode = decodeValue(bytes, offset);
305
- offset = keyNode.offset;
306
- const valueNode = decodeValue(bytes, offset);
307
- offset = valueNode.offset;
308
- entries.push({key: keyNode.value, keyNode, valueNode});
309
- obj[String(keyNode.value)] = valueNode.value;
310
- }
311
- return {value: obj, format: "map16", entries, offset, raw: bytes.slice(0, offset)};
312
- }
313
- default:
314
- throw new Error(`Unsupported msgpack token 0x${head.toString(16)}`);
315
- }
316
- }
317
-
318
- // Value-only decoder used for all inbound traffic.
319
- //
320
- // `decodeValue` above annotates every node with its `raw` byte slice and format
321
- // so outgoing commands can be re-encoded byte-for-byte. Containers slice from
322
- // the start of the buffer, which makes decoding quadratic in packet size, and
323
- // `decodeMsgpack` discarded all of it. This path allocates only the decoded
324
- // values. The annotated decoder stays exported for the command-signing path and
325
- // external tooling.
326
- let cursor = 0;
327
-
328
- function readFast(bytes) {
329
- const head = bytes[cursor++];
330
-
331
- if (head <= 0x7f) return head;
332
- if (head >= 0xe0) return (head << 24) >> 24;
333
-
334
- if ((head & 0xf0) === 0x80) return readMapFast(bytes, head & 0x0f);
335
- if ((head & 0xf0) === 0x90) return readArrayFast(bytes, head & 0x0f);
336
- if ((head & 0xe0) === 0xa0) return readStrFast(bytes, head & 0x1f);
337
-
338
- switch (head) {
339
- case 0xc0:
340
- return null;
341
- case 0xc2:
342
- return false;
343
- case 0xc3:
344
- return true;
345
- case 0xc4:
346
- return readBinFast(bytes, bytes[cursor++]);
347
- case 0xc5: {
348
- const len = (bytes[cursor] << 8) | bytes[cursor + 1];
349
- cursor += 2;
350
- return readBinFast(bytes, len);
351
- }
352
- case 0xc6: {
353
- const len = (bytes[cursor] * 0x1000000) + ((bytes[cursor + 1] << 16) | (bytes[cursor + 2] << 8) | bytes[cursor + 3]);
354
- cursor += 4;
355
- return readBinFast(bytes, len);
356
- }
357
- case 0xca: {
358
- const value = new DataView(bytes.buffer, bytes.byteOffset + cursor, 4).getFloat32(0, false);
359
- cursor += 4;
360
- return value;
361
- }
362
- case 0xcb: {
363
- const value = new DataView(bytes.buffer, bytes.byteOffset + cursor, 8).getFloat64(0, false);
364
- cursor += 8;
365
- return value;
366
- }
367
- case 0xcc:
368
- return bytes[cursor++];
369
- case 0xcd: {
370
- const value = (bytes[cursor] << 8) | bytes[cursor + 1];
371
- cursor += 2;
372
- return value;
373
- }
374
- case 0xce: {
375
- const value = (((bytes[cursor] * 0x1000000) + ((bytes[cursor + 1] << 16) | (bytes[cursor + 2] << 8) | bytes[cursor + 3])) >>> 0);
376
- cursor += 4;
377
- return value;
378
- }
379
- case 0xd0:
380
- return (bytes[cursor++] << 24) >> 24;
381
- case 0xd1: {
382
- const value = ((((bytes[cursor] << 8) | bytes[cursor + 1]) << 16) >> 16);
383
- cursor += 2;
384
- return value;
385
- }
386
- case 0xd2: {
387
- const value = ((bytes[cursor] << 24) | (bytes[cursor + 1] << 16) | (bytes[cursor + 2] << 8) | bytes[cursor + 3]) | 0;
388
- cursor += 4;
389
- return value;
390
- }
391
- case 0xd9:
392
- return readStrFast(bytes, bytes[cursor++]);
393
- case 0xda: {
394
- const len = (bytes[cursor] << 8) | bytes[cursor + 1];
395
- cursor += 2;
396
- return readStrFast(bytes, len);
397
- }
398
- case 0xdc: {
399
- const count = (bytes[cursor] << 8) | bytes[cursor + 1];
400
- cursor += 2;
401
- return readArrayFast(bytes, count);
402
- }
403
- case 0xde: {
404
- const count = (bytes[cursor] << 8) | bytes[cursor + 1];
405
- cursor += 2;
406
- return readMapFast(bytes, count);
407
- }
408
- default:
409
- throw new Error(`Unsupported msgpack token 0x${head.toString(16)}`);
410
- }
411
- }
412
-
413
- function readStrFast(bytes, len) {
414
- const start = cursor;
415
- cursor += len;
416
- // subarray, not slice: TextDecoder copies into the result string anyway.
417
- return decoder.decode(bytes.subarray(start, cursor));
418
- }
419
-
420
- function readBinFast(bytes, len) {
421
- const start = cursor;
422
- cursor += len;
423
- // slice, not subarray: callers retain these payloads past the socket buffer.
424
- return bytes.slice(start, cursor);
425
- }
426
-
427
- function readArrayFast(bytes, count) {
428
- const items = new Array(count);
429
- for (let i = 0; i < count; i++) items[i] = readFast(bytes);
430
- return items;
431
- }
432
-
433
- function readMapFast(bytes, count) {
434
- const obj = {};
435
- for (let i = 0; i < count; i++) {
436
- const key = readFast(bytes);
437
- obj[typeof key === "string" ? key : String(key)] = readFast(bytes);
438
- }
439
- return obj;
440
- }
441
-
442
- function decodeMsgpack(bytes) {
443
- const input = toUint8Array(bytes);
444
- cursor = 0;
445
- return readFast(input);
446
- }
447
-
448
- // Growable output buffer. The recursive encoder used to build an array of small
449
- // Uint8Array fragments per value and concatenate them at every nesting level.
450
- class MsgpackWriter {
451
- constructor(capacity = 256) {
452
- this.bytes = new Uint8Array(capacity);
453
- this.length = 0;
454
- }
455
-
456
- #reserve(extra) {
457
- const needed = this.length + extra;
458
- if (needed <= this.bytes.length) return;
459
- let size = this.bytes.length || 64;
460
- while (size < needed) size *= 2;
461
- const grown = new Uint8Array(size);
462
- grown.set(this.bytes.subarray(0, this.length));
463
- this.bytes = grown;
464
- }
465
-
466
- byte(value) {
467
- this.#reserve(1);
468
- this.bytes[this.length++] = value & 0xff;
469
- return this;
470
- }
471
-
472
- raw(chunk) {
473
- this.#reserve(chunk.length);
474
- this.bytes.set(chunk, this.length);
475
- this.length += chunk.length;
476
- return this;
477
- }
478
-
479
- result() {
480
- return this.bytes.slice(0, this.length);
481
- }
482
- }
483
-
484
- function writeMsgpack(writer, value) {
485
- if (value == null) return writer.byte(0xc0);
486
- if (typeof value === "boolean") return writer.byte(value ? 0xc3 : 0xc2);
487
- if (typeof value === "number") return writer.raw(encodeMsgpackNumber(value));
488
- if (typeof value === "string") return writer.raw(encodeStringBytes(value));
489
-
490
- if (value instanceof Uint8Array || value instanceof ArrayBuffer || ArrayBuffer.isView(value)) {
491
- const bytes = toUint8Array(value);
492
- if (bytes.length <= 0xff) writer.byte(0xc4).byte(bytes.length);
493
- else if (bytes.length <= 0xffff) writer.byte(0xc5).byte(bytes.length >>> 8).byte(bytes.length);
494
- else writer.byte(0xc6).byte(bytes.length >>> 24).byte(bytes.length >>> 16).byte(bytes.length >>> 8).byte(bytes.length);
495
- return writer.raw(bytes);
496
- }
497
-
498
- if (Array.isArray(value)) {
499
- const len = value.length;
500
- if (len <= 15) writer.byte(0x90 | len);
501
- else writer.byte(0xdc).byte(len >>> 8).byte(len);
502
- for (const item of value) writeMsgpack(writer, item);
503
- return writer;
504
- }
505
-
506
- if (typeof value === "object") {
507
- const entries = Object.entries(value);
508
- if (entries.length <= 15) writer.byte(0x80 | entries.length);
509
- else writer.byte(0xde).byte(entries.length >>> 8).byte(entries.length);
510
- for (const [key, val] of entries) {
511
- writer.raw(encodeStringBytes(key));
512
- writeMsgpack(writer, val);
513
- }
514
- return writer;
515
- }
516
-
517
- throw new Error(`Unsupported msgpack value: ${typeof value}`);
518
- }
519
-
520
- function encodeMsgpackNumber(value) {
521
- if (!Number.isInteger(value)) return encodeNumberWithFormat(value, "float32");
522
- if (value >= 0) {
523
- if (value <= 0x7f) return encodeNumberWithFormat(value, "positive-fixint");
524
- if (value <= 0xff) return encodeNumberWithFormat(value, "uint8");
525
- if (value <= 0xffff) return encodeNumberWithFormat(value, "uint16");
526
- return encodeNumberWithFormat(value, "uint32");
527
- }
528
- if (value >= -32) return encodeNumberWithFormat(value, "negative-fixint");
529
- if (value >= -128) return encodeNumberWithFormat(value, "int8");
530
- if (value >= -32768) return encodeNumberWithFormat(value, "int16");
531
- return encodeNumberWithFormat(value, "int32");
532
- }
533
-
534
- function encodeMsgpack(value) {
535
- // Scalars need no buffer at all.
536
- if (value == null) return Uint8Array.of(0xc0);
537
- if (typeof value === "boolean") return Uint8Array.of(value ? 0xc3 : 0xc2);
538
- if (typeof value === "number") return encodeMsgpackNumber(value);
539
- if (typeof value === "string") return encodeStringBytes(value);
540
- const writer = new MsgpackWriter();
541
- writeMsgpack(writer, value);
542
- return writer.result();
543
- }
544
-
545
- export {
546
- cloneDragValue,
547
- cloneCommand,
548
- encodeStringBytes,
549
- encodeNumberWithFormat,
550
- encodeMapHeader,
551
- encodeValue,
552
- decodeValue,
553
- decodeMsgpack,
554
- encodeMsgpack
555
- };
1
+ import {COMMAND_DEFAULT_FORMATS, COMMAND_FIELDS, decoder, encoder} from "../../constants.js";
2
+ import {concatBytes, toUint8Array, valuesEqual} from "./binary.js";
3
+
4
+ function cloneDragValue(drag) {
5
+ if (!drag || typeof drag !== "object") return null;
6
+ return {
7
+ source: Number(drag.source),
8
+ target: Number(drag.target),
9
+ split: Boolean(drag.split)
10
+ };
11
+ }
12
+
13
+ function cloneCommand(command) {
14
+ const out = {};
15
+ for (const key of COMMAND_FIELDS) {
16
+ out[key] = key === "drag" ? cloneDragValue(command[key]) : command[key];
17
+ }
18
+ return out;
19
+ }
20
+
21
+ function encodeStringBytes(text) {
22
+ const bytes = encoder.encode(String(text));
23
+ const length = bytes.length;
24
+ if (length <= 31) {
25
+ const out = new Uint8Array(1 + length);
26
+ out[0] = 0xa0 | length;
27
+ out.set(bytes, 1);
28
+ return out;
29
+ }
30
+ if (length <= 0xff) {
31
+ const out = new Uint8Array(2 + length);
32
+ out[0] = 0xd9;
33
+ out[1] = length;
34
+ out.set(bytes, 2);
35
+ return out;
36
+ }
37
+ const out = new Uint8Array(3 + length);
38
+ out[0] = 0xda;
39
+ out[1] = (length >>> 8) & 0xff;
40
+ out[2] = length & 0xff;
41
+ out.set(bytes, 3);
42
+ return out;
43
+ }
44
+
45
+ function encodeNumberWithFormat(value, format) {
46
+ const number = Number(value);
47
+ switch (format) {
48
+ case "positive-fixint":
49
+ return Uint8Array.of(number & 0x7f);
50
+ case "negative-fixint":
51
+ return Uint8Array.of(number & 0xff);
52
+ case "uint8":
53
+ return Uint8Array.of(0xcc, number & 0xff);
54
+ case "uint16":
55
+ return Uint8Array.of(0xcd, (number >>> 8) & 0xff, number & 0xff);
56
+ case "uint32":
57
+ return Uint8Array.of(0xce, (number >>> 24) & 0xff, (number >>> 16) & 0xff, (number >>> 8) & 0xff, number & 0xff);
58
+ case "int8":
59
+ return Uint8Array.of(0xd0, number & 0xff);
60
+ case "int16":
61
+ return Uint8Array.of(0xd1, (number >> 8) & 0xff, number & 0xff);
62
+ case "int32":
63
+ return Uint8Array.of(0xd2, (number >> 24) & 0xff, (number >> 16) & 0xff, (number >> 8) & 0xff, number & 0xff);
64
+ case "float64": {
65
+ const out = new Uint8Array(9);
66
+ out[0] = 0xcb;
67
+ new DataView(out.buffer).setFloat64(1, number, false);
68
+ return out;
69
+ }
70
+ case "float32":
71
+ default: {
72
+ const out = new Uint8Array(5);
73
+ out[0] = 0xca;
74
+ new DataView(out.buffer).setFloat32(1, number, false);
75
+ return out;
76
+ }
77
+ }
78
+ }
79
+
80
+ function encodeMapHeader(length, originalHeaderBytes = null) {
81
+ if (originalHeaderBytes && originalHeaderBytes.length > 0) return originalHeaderBytes;
82
+ if (length <= 15) return Uint8Array.of(0x80 | length);
83
+ return Uint8Array.of(0xde, (length >>> 8) & 0xff, length & 0xff);
84
+ }
85
+
86
+ function encodeValue(key, value, entry) {
87
+ if (entry && valuesEqual(value, entry.valueNode.value)) return entry.valueNode.raw;
88
+ if (value == null) return Uint8Array.of(0xc0);
89
+ if (typeof value === "boolean") return Uint8Array.of(value ? 0xc3 : 0xc2);
90
+ if (typeof value === "number") {
91
+ const schemaFormat = COMMAND_DEFAULT_FORMATS[key];
92
+ let format = schemaFormat && schemaFormat !== "nil" ? schemaFormat : null;
93
+ if (!format) {
94
+ if (!Number.isInteger(value)) format = "float32";
95
+ else if (value >= 0) {
96
+ if (value <= 0x7f) format = "positive-fixint";
97
+ else if (value <= 0xff) format = "uint8";
98
+ else if (value <= 0xffff) format = "uint16";
99
+ else format = "uint32";
100
+ } else if (value >= -32) format = "negative-fixint";
101
+ else if (value >= -128) format = "int8";
102
+ else if (value >= -32768) format = "int16";
103
+ else format = "int32";
104
+ }
105
+ return encodeNumberWithFormat(value, format);
106
+ }
107
+ if (typeof value === "string") return encodeStringBytes(value);
108
+ if (key === "drag" && typeof value === "object") {
109
+ const sourceEntry = entry?.valueNode?.entries?.find((item) => String(item.key) === "source")?.valueNode;
110
+ const targetEntry = entry?.valueNode?.entries?.find((item) => String(item.key) === "target")?.valueNode;
111
+ return concatBytes([
112
+ Uint8Array.of(0x83),
113
+ encodeStringBytes("source"),
114
+ encodeNumberWithFormat(Number(value.source || 0), sourceEntry?.format || "positive-fixint"),
115
+ encodeStringBytes("target"),
116
+ encodeNumberWithFormat(Number(value.target || 0), targetEntry?.format || "positive-fixint"),
117
+ encodeStringBytes("split"),
118
+ Uint8Array.of(Boolean(value.split) ? 0xc3 : 0xc2)
119
+ ]);
120
+ }
121
+ throw new Error(`Unsupported command field "${key}"`);
122
+ }
123
+
124
+ function decodeValue(bytes, offset = 0) {
125
+ const head = bytes[offset++];
126
+ if (head <= 0x7f) return {value: head, format: "positive-fixint", offset, raw: bytes.slice(offset - 1, offset)};
127
+ if (head >= 0xe0) return {
128
+ value: (head << 24) >> 24,
129
+ format: "negative-fixint",
130
+ offset,
131
+ raw: bytes.slice(offset - 1, offset)
132
+ };
133
+ if ((head & 0xf0) === 0x80) {
134
+ const count = head & 0x0f;
135
+ const entries = [];
136
+ const obj = {};
137
+ for (let i = 0; i < count; i++) {
138
+ const keyNode = decodeValue(bytes, offset);
139
+ offset = keyNode.offset;
140
+ const valueNode = decodeValue(bytes, offset);
141
+ offset = valueNode.offset;
142
+ entries.push({key: keyNode.value, keyNode, valueNode});
143
+ obj[String(keyNode.value)] = valueNode.value;
144
+ }
145
+ return {
146
+ value: obj,
147
+ format: "fixmap",
148
+ entries,
149
+ headerBytes: bytes.slice(offset - 1 - (count * 2), offset),
150
+ offset,
151
+ raw: bytes.slice(offset - (offset - (offset - 1)), offset)
152
+ };
153
+ }
154
+ if ((head & 0xf0) === 0x90) {
155
+ const count = head & 0x0f;
156
+ const items = [];
157
+ for (let i = 0; i < count; i++) {
158
+ const item = decodeValue(bytes, offset);
159
+ offset = item.offset;
160
+ items.push(item);
161
+ }
162
+ return {value: items.map((item) => item.value), format: "fixarray", items, offset, raw: bytes.slice(0, offset)};
163
+ }
164
+ if ((head & 0xe0) === 0xa0) {
165
+ const len = head & 0x1f;
166
+ const start = offset;
167
+ const end = start + len;
168
+ return {
169
+ value: decoder.decode(bytes.slice(start, end)),
170
+ format: "fixstr",
171
+ offset: end,
172
+ raw: bytes.slice(offset - 1, end)
173
+ };
174
+ }
175
+ switch (head) {
176
+ case 0xc0:
177
+ return {value: null, format: "nil", offset, raw: bytes.slice(offset - 1, offset)};
178
+ case 0xc2:
179
+ return {value: false, format: "bool", offset, raw: bytes.slice(offset - 1, offset)};
180
+ case 0xc3:
181
+ return {value: true, format: "bool", offset, raw: bytes.slice(offset - 1, offset)};
182
+ case 0xc4: {
183
+ const len = bytes[offset++];
184
+ const start = offset;
185
+ const end = start + len;
186
+ return {value: bytes.slice(start, end), format: "bin8", offset: end, raw: bytes.slice(start - 2, end)};
187
+ }
188
+ case 0xc5: {
189
+ const len = (bytes[offset] << 8) | bytes[offset + 1];
190
+ offset += 2;
191
+ const start = offset;
192
+ const end = start + len;
193
+ return {value: bytes.slice(start, end), format: "bin16", offset: end, raw: bytes.slice(start - 3, end)};
194
+ }
195
+ case 0xc6: {
196
+ const len = (bytes[offset] * 0x1000000) + ((bytes[offset + 1] << 16) | (bytes[offset + 2] << 8) | bytes[offset + 3]);
197
+ offset += 4;
198
+ const start = offset;
199
+ const end = start + len;
200
+ return {value: bytes.slice(start, end), format: "bin32", offset: end, raw: bytes.slice(start - 5, end)};
201
+ }
202
+ case 0xca:
203
+ return {
204
+ value: new DataView(bytes.buffer, bytes.byteOffset + offset, 4).getFloat32(0, false),
205
+ format: "float32",
206
+ offset: offset + 4,
207
+ raw: bytes.slice(offset - 1, offset + 4)
208
+ };
209
+ case 0xcb:
210
+ return {
211
+ value: new DataView(bytes.buffer, bytes.byteOffset + offset, 8).getFloat64(0, false),
212
+ format: "float64",
213
+ offset: offset + 8,
214
+ raw: bytes.slice(offset - 1, offset + 8)
215
+ };
216
+ case 0xcc:
217
+ return {
218
+ value: bytes[offset],
219
+ format: "uint8",
220
+ offset: offset + 1,
221
+ raw: bytes.slice(offset - 1, offset + 1)
222
+ };
223
+ case 0xcd:
224
+ return {
225
+ value: (bytes[offset] << 8) | bytes[offset + 1],
226
+ format: "uint16",
227
+ offset: offset + 2,
228
+ raw: bytes.slice(offset - 1, offset + 2)
229
+ };
230
+ case 0xce:
231
+ return {
232
+ value: (((bytes[offset] * 0x1000000) + ((bytes[offset + 1] << 16) | (bytes[offset + 2] << 8) | bytes[offset + 3])) >>> 0),
233
+ format: "uint32",
234
+ offset: offset + 4,
235
+ raw: bytes.slice(offset - 1, offset + 4)
236
+ };
237
+ case 0xd0:
238
+ return {
239
+ value: (bytes[offset] << 24) >> 24,
240
+ format: "int8",
241
+ offset: offset + 1,
242
+ raw: bytes.slice(offset - 1, offset + 1)
243
+ };
244
+ case 0xd1:
245
+ return {
246
+ value: new DataView(bytes.buffer, bytes.byteOffset + offset, 2).getInt16(0, false),
247
+ format: "int16",
248
+ offset: offset + 2,
249
+ raw: bytes.slice(offset - 1, offset + 2)
250
+ };
251
+ case 0xd2:
252
+ return {
253
+ value: new DataView(bytes.buffer, bytes.byteOffset + offset, 4).getInt32(0, false),
254
+ format: "int32",
255
+ offset: offset + 4,
256
+ raw: bytes.slice(offset - 1, offset + 4)
257
+ };
258
+ case 0xd9: {
259
+ const len = bytes[offset++];
260
+ const start = offset;
261
+ const end = start + len;
262
+ return {
263
+ value: decoder.decode(bytes.slice(start, end)),
264
+ format: "str8",
265
+ offset: end,
266
+ raw: bytes.slice(start - 2, end)
267
+ };
268
+ }
269
+ case 0xda: {
270
+ const len = (bytes[offset] << 8) | bytes[offset + 1];
271
+ offset += 2;
272
+ const start = offset;
273
+ const end = start + len;
274
+ return {
275
+ value: decoder.decode(bytes.slice(start, end)),
276
+ format: "str16",
277
+ offset: end,
278
+ raw: bytes.slice(start - 3, end)
279
+ };
280
+ }
281
+ case 0xdc: {
282
+ const count = (bytes[offset] << 8) | bytes[offset + 1];
283
+ offset += 2;
284
+ const items = [];
285
+ for (let i = 0; i < count; i++) {
286
+ const item = decodeValue(bytes, offset);
287
+ offset = item.offset;
288
+ items.push(item);
289
+ }
290
+ return {
291
+ value: items.map((item) => item.value),
292
+ format: "array16",
293
+ items,
294
+ offset,
295
+ raw: bytes.slice(0, offset)
296
+ };
297
+ }
298
+ case 0xde: {
299
+ const count = (bytes[offset] << 8) | bytes[offset + 1];
300
+ offset += 2;
301
+ const entries = [];
302
+ const obj = {};
303
+ for (let i = 0; i < count; i++) {
304
+ const keyNode = decodeValue(bytes, offset);
305
+ offset = keyNode.offset;
306
+ const valueNode = decodeValue(bytes, offset);
307
+ offset = valueNode.offset;
308
+ entries.push({key: keyNode.value, keyNode, valueNode});
309
+ obj[String(keyNode.value)] = valueNode.value;
310
+ }
311
+ return {value: obj, format: "map16", entries, offset, raw: bytes.slice(0, offset)};
312
+ }
313
+ default:
314
+ throw new Error(`Unsupported msgpack token 0x${head.toString(16)}`);
315
+ }
316
+ }
317
+
318
+ // Value-only decoder used for all inbound traffic.
319
+ //
320
+ // `decodeValue` above annotates every node with its `raw` byte slice and format
321
+ // so outgoing commands can be re-encoded byte-for-byte. Containers slice from
322
+ // the start of the buffer, which makes decoding quadratic in packet size, and
323
+ // `decodeMsgpack` discarded all of it. This path allocates only the decoded
324
+ // values. The annotated decoder stays exported for the command-signing path and
325
+ // external tooling.
326
+ let cursor = 0;
327
+
328
+ function readFast(bytes) {
329
+ const head = bytes[cursor++];
330
+
331
+ if (head <= 0x7f) return head;
332
+ if (head >= 0xe0) return (head << 24) >> 24;
333
+
334
+ if ((head & 0xf0) === 0x80) return readMapFast(bytes, head & 0x0f);
335
+ if ((head & 0xf0) === 0x90) return readArrayFast(bytes, head & 0x0f);
336
+ if ((head & 0xe0) === 0xa0) return readStrFast(bytes, head & 0x1f);
337
+
338
+ switch (head) {
339
+ case 0xc0:
340
+ return null;
341
+ case 0xc2:
342
+ return false;
343
+ case 0xc3:
344
+ return true;
345
+ case 0xc4:
346
+ return readBinFast(bytes, bytes[cursor++]);
347
+ case 0xc5: {
348
+ const len = (bytes[cursor] << 8) | bytes[cursor + 1];
349
+ cursor += 2;
350
+ return readBinFast(bytes, len);
351
+ }
352
+ case 0xc6: {
353
+ const len = (bytes[cursor] * 0x1000000) + ((bytes[cursor + 1] << 16) | (bytes[cursor + 2] << 8) | bytes[cursor + 3]);
354
+ cursor += 4;
355
+ return readBinFast(bytes, len);
356
+ }
357
+ case 0xca: {
358
+ const value = new DataView(bytes.buffer, bytes.byteOffset + cursor, 4).getFloat32(0, false);
359
+ cursor += 4;
360
+ return value;
361
+ }
362
+ case 0xcb: {
363
+ const value = new DataView(bytes.buffer, bytes.byteOffset + cursor, 8).getFloat64(0, false);
364
+ cursor += 8;
365
+ return value;
366
+ }
367
+ case 0xcc:
368
+ return bytes[cursor++];
369
+ case 0xcd: {
370
+ const value = (bytes[cursor] << 8) | bytes[cursor + 1];
371
+ cursor += 2;
372
+ return value;
373
+ }
374
+ case 0xce: {
375
+ const value = (((bytes[cursor] * 0x1000000) + ((bytes[cursor + 1] << 16) | (bytes[cursor + 2] << 8) | bytes[cursor + 3])) >>> 0);
376
+ cursor += 4;
377
+ return value;
378
+ }
379
+ case 0xd0:
380
+ return (bytes[cursor++] << 24) >> 24;
381
+ case 0xd1: {
382
+ const value = ((((bytes[cursor] << 8) | bytes[cursor + 1]) << 16) >> 16);
383
+ cursor += 2;
384
+ return value;
385
+ }
386
+ case 0xd2: {
387
+ const value = ((bytes[cursor] << 24) | (bytes[cursor + 1] << 16) | (bytes[cursor + 2] << 8) | bytes[cursor + 3]) | 0;
388
+ cursor += 4;
389
+ return value;
390
+ }
391
+ case 0xd9:
392
+ return readStrFast(bytes, bytes[cursor++]);
393
+ case 0xda: {
394
+ const len = (bytes[cursor] << 8) | bytes[cursor + 1];
395
+ cursor += 2;
396
+ return readStrFast(bytes, len);
397
+ }
398
+ case 0xdc: {
399
+ const count = (bytes[cursor] << 8) | bytes[cursor + 1];
400
+ cursor += 2;
401
+ return readArrayFast(bytes, count);
402
+ }
403
+ case 0xde: {
404
+ const count = (bytes[cursor] << 8) | bytes[cursor + 1];
405
+ cursor += 2;
406
+ return readMapFast(bytes, count);
407
+ }
408
+ default:
409
+ throw new Error(`Unsupported msgpack token 0x${head.toString(16)}`);
410
+ }
411
+ }
412
+
413
+ function readStrFast(bytes, len) {
414
+ const start = cursor;
415
+ cursor += len;
416
+ // subarray, not slice: TextDecoder copies into the result string anyway.
417
+ return decoder.decode(bytes.subarray(start, cursor));
418
+ }
419
+
420
+ function readBinFast(bytes, len) {
421
+ const start = cursor;
422
+ cursor += len;
423
+ // slice, not subarray: callers retain these payloads past the socket buffer.
424
+ return bytes.slice(start, cursor);
425
+ }
426
+
427
+ function readArrayFast(bytes, count) {
428
+ const items = new Array(count);
429
+ for (let i = 0; i < count; i++) items[i] = readFast(bytes);
430
+ return items;
431
+ }
432
+
433
+ function readMapFast(bytes, count) {
434
+ const obj = {};
435
+ for (let i = 0; i < count; i++) {
436
+ const key = readFast(bytes);
437
+ obj[typeof key === "string" ? key : String(key)] = readFast(bytes);
438
+ }
439
+ return obj;
440
+ }
441
+
442
+ function decodeMsgpack(bytes) {
443
+ const input = toUint8Array(bytes);
444
+ cursor = 0;
445
+ return readFast(input);
446
+ }
447
+
448
+ // Growable output buffer. The recursive encoder used to build an array of small
449
+ // Uint8Array fragments per value and concatenate them at every nesting level.
450
+ class MsgpackWriter {
451
+ constructor(capacity = 256) {
452
+ this.bytes = new Uint8Array(capacity);
453
+ this.length = 0;
454
+ }
455
+
456
+ #reserve(extra) {
457
+ const needed = this.length + extra;
458
+ if (needed <= this.bytes.length) return;
459
+ let size = this.bytes.length || 64;
460
+ while (size < needed) size *= 2;
461
+ const grown = new Uint8Array(size);
462
+ grown.set(this.bytes.subarray(0, this.length));
463
+ this.bytes = grown;
464
+ }
465
+
466
+ byte(value) {
467
+ this.#reserve(1);
468
+ this.bytes[this.length++] = value & 0xff;
469
+ return this;
470
+ }
471
+
472
+ raw(chunk) {
473
+ this.#reserve(chunk.length);
474
+ this.bytes.set(chunk, this.length);
475
+ this.length += chunk.length;
476
+ return this;
477
+ }
478
+
479
+ result() {
480
+ return this.bytes.slice(0, this.length);
481
+ }
482
+ }
483
+
484
+ function writeMsgpack(writer, value) {
485
+ if (value == null) return writer.byte(0xc0);
486
+ if (typeof value === "boolean") return writer.byte(value ? 0xc3 : 0xc2);
487
+ if (typeof value === "number") return writer.raw(encodeMsgpackNumber(value));
488
+ if (typeof value === "string") return writer.raw(encodeStringBytes(value));
489
+
490
+ if (value instanceof Uint8Array || value instanceof ArrayBuffer || ArrayBuffer.isView(value)) {
491
+ const bytes = toUint8Array(value);
492
+ if (bytes.length <= 0xff) writer.byte(0xc4).byte(bytes.length);
493
+ else if (bytes.length <= 0xffff) writer.byte(0xc5).byte(bytes.length >>> 8).byte(bytes.length);
494
+ else writer.byte(0xc6).byte(bytes.length >>> 24).byte(bytes.length >>> 16).byte(bytes.length >>> 8).byte(bytes.length);
495
+ return writer.raw(bytes);
496
+ }
497
+
498
+ if (Array.isArray(value)) {
499
+ const len = value.length;
500
+ if (len <= 15) writer.byte(0x90 | len);
501
+ else writer.byte(0xdc).byte(len >>> 8).byte(len);
502
+ for (const item of value) writeMsgpack(writer, item);
503
+ return writer;
504
+ }
505
+
506
+ if (typeof value === "object") {
507
+ const entries = Object.entries(value);
508
+ if (entries.length <= 15) writer.byte(0x80 | entries.length);
509
+ else writer.byte(0xde).byte(entries.length >>> 8).byte(entries.length);
510
+ for (const [key, val] of entries) {
511
+ writer.raw(encodeStringBytes(key));
512
+ writeMsgpack(writer, val);
513
+ }
514
+ return writer;
515
+ }
516
+
517
+ throw new Error(`Unsupported msgpack value: ${typeof value}`);
518
+ }
519
+
520
+ function encodeMsgpackNumber(value) {
521
+ if (!Number.isInteger(value)) return encodeNumberWithFormat(value, "float32");
522
+ if (value >= 0) {
523
+ if (value <= 0x7f) return encodeNumberWithFormat(value, "positive-fixint");
524
+ if (value <= 0xff) return encodeNumberWithFormat(value, "uint8");
525
+ if (value <= 0xffff) return encodeNumberWithFormat(value, "uint16");
526
+ return encodeNumberWithFormat(value, "uint32");
527
+ }
528
+ if (value >= -32) return encodeNumberWithFormat(value, "negative-fixint");
529
+ if (value >= -128) return encodeNumberWithFormat(value, "int8");
530
+ if (value >= -32768) return encodeNumberWithFormat(value, "int16");
531
+ return encodeNumberWithFormat(value, "int32");
532
+ }
533
+
534
+ function encodeMsgpack(value) {
535
+ // Scalars need no buffer at all.
536
+ if (value == null) return Uint8Array.of(0xc0);
537
+ if (typeof value === "boolean") return Uint8Array.of(value ? 0xc3 : 0xc2);
538
+ if (typeof value === "number") return encodeMsgpackNumber(value);
539
+ if (typeof value === "string") return encodeStringBytes(value);
540
+ const writer = new MsgpackWriter();
541
+ writeMsgpack(writer, value);
542
+ return writer.result();
543
+ }
544
+
545
+ export {
546
+ cloneDragValue,
547
+ cloneCommand,
548
+ encodeStringBytes,
549
+ encodeNumberWithFormat,
550
+ encodeMapHeader,
551
+ encodeValue,
552
+ decodeValue,
553
+ decodeMsgpack,
554
+ encodeMsgpack
555
+ };