@hazae41/bobine 0.0.11 → 0.0.13

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.
package/README.md CHANGED
@@ -132,150 +132,45 @@ declare function add(x: externref, y: externref): externref
132
132
 
133
133
  You can pass bytes between modules by storing them in the blob storage and loading them via reference
134
134
 
135
- - `blobs.save(offset: i32, length: i32): blobref` = save `length` bytes at `offset` of your memory to the blob storage
136
-
137
- - `blobs.load(blob: blobref, offset: i32): void` = load some blob into your memory at `offset`
138
-
139
- - `blobs.equals(left: blobref, right: blobref): bool` = check if two blobs are equals without loading them into memory
140
-
141
- - `blobs.concat(left: blobref, right: blobref): blobref` = concatenate two blobs without loading them into memory
142
-
143
- - `blob.to_hex/from_hex/to_base64/from_base64(blob: blobref): blobref` = convert blobs to/from hex/base64 without loading them into memory
144
-
145
135
  #### BigInts module
146
136
 
147
- You can work with infinite-precision bigints
148
-
149
- - `bigints.add(left: bigintref, right: bigintref): bigintref` = add two bigints
150
-
151
- - `bigints.sub(left: bigintref, right: bigintref): bigintref` = subtract two bigints
152
-
153
- - `bigints.mul(left: bigintref, right: bigintref): bigintref` = multiply two bigints
154
-
155
- - `bigints.div(left: bigintref, right: bigintref): bigintref` = divide two bigints
137
+ You can work with infinite-precision bigints and convert them with blobs and texts
156
138
 
157
- - `bigints.pow(left: bigintref, right: bigintref): bigintref` = left ** right
158
-
159
- - `bigints.encode(bigint: bigintref): blobref` = convert bigint to bytes
160
-
161
- - `bigints.decode(base16: blobref): bigintref` = convert bytes to bigint
162
-
163
- - `bigints.to_base16(bigint: bigintref): blobref` = convert bigint to hex utf8 bytes
164
-
165
- - `bigints.from_base16(base16: blobref): bigintref` = convert hex utf8 bytes to bigint
166
-
167
- - `bigints.to_base10(bigint: bigintref): blobref` = convert bigint to base10 utf8 bytes
168
-
169
- - `bigints.from_base10(base16: blobref): bigintref` = convert base10 utf8 bytes to bigint
139
+ And many others
170
140
 
171
141
  #### Packs module
172
142
 
173
143
  You can pack various arguments (numbers, refs) into a pack which can be passed between modules and/or encoded/decoded into bytes
174
144
 
175
- - `packs.create(...values: any[]): packref` = create a new pack from the provided values (number, blobref, packref, null)
176
-
177
- - `packs.encode(pack: packref): blobref` = encodes values into bytes using the following pseudocode
178
-
179
- ```tsx
180
- function writePack(pack: packref) {
181
- for (const value of values) {
182
- if (isNull(value)) {
183
- writeUint8(1)
184
- continue
185
- }
186
-
187
- if (isNumber(value)) {
188
- writeUint8(2)
189
- writeFloat64(value, "little-endian")
190
- continue
191
- }
192
-
193
- if (isBigInt(value)) {
194
- writeUint8(3)
195
- writeUint32(value.toHex().length, "little-endian")
196
- writeBytes(value.toHex())
197
- continue
198
- }
199
-
200
- if (isBlobref(value)) {
201
- writeUint8(4)
202
- writeUint32(value.length, "little-endian")
203
- writeBytes(value)
204
- continue
205
- }
206
-
207
- if (isPackref(value)) {
208
- writeUint8(5)
209
- writePack(value)
210
- continue
211
- }
212
-
213
- throw new Error()
214
- }
215
-
216
- writeUint8(0)
217
- }
218
- ```
219
-
220
- - `packs.decode(blob: blobref): packref` = decodes bytes into a pack of values using the same pseudocode but for reading
221
-
222
- - `packs.concat(left: packref, right: packref)` = concatenate two packs into one (basically does `[...left, ...right]`)
223
-
224
- - `packs.get<T>(pack: packref, index: i32): T` = get the value of a pack at `index` (throws if not found)
225
-
226
- - `packs.length(pack: packref): i32` = get the length of a pack
227
-
228
145
  #### Environment module
229
146
 
230
147
  Get infos about the executing environment
231
148
 
232
- - `env.mode: i32` = `1` if execution, `2` is simulation
233
-
234
- - `env.uuid(): blobref` = get the unique uuid of this environment (similar to a chain id)
235
-
236
149
  #### Modules module
237
150
 
238
151
  Modules are identified by their address as a blob of bytes (pure sha256-output 32-length bytes without any encoding)
239
152
 
240
- - `modules.load(module: blobref): blobref` = get the code of module as a blob
241
-
242
- - `modules.call(module: blobref, method: blobref, params: packref): packref` = dynamically call a module method with the given params as pack and return value as a 1-length pack
243
-
244
- - `modules.create(code: blobref, salt: blobref): blobref` = dynamically create a new module with the given code and salt, returns the module address
245
-
246
- - `modules.self(): blobref` = get your module address as blob
153
+ You can dynamically create modules, call modules, get their bytecode
247
154
 
248
155
  #### Storage module
249
156
 
250
- You can use a private storage (it works like storage and events at the same time)
251
-
252
- - `storage.set(key: blobref, value: blobref): void` = set some value to storage at key
253
-
254
- - `storage.get(key: blobref): blobref` = get the latest value from storage at key
157
+ You can use a private key-value storage (it works like storage and events at the same time)
255
158
 
256
159
  #### SHA-256 module
257
160
 
258
161
  Use the SHA-256 hashing algorithm
259
162
 
260
- - `sha256.digest(payload: blobref): blobref` = hash the payload and returns the digest
261
-
262
163
  #### Ed25519 module
263
164
 
264
- Use the Ed25519 signing algorithm
265
-
266
- - `ed25519.verify(pubkey: blobref, signature: blobref, payload: blobref): boolean` = verify a signature
267
-
268
- - `ed25519.sign(payload: blobref): blobref` = (experimental) sign payload using the miner's private key
165
+ Use the Ed25519 signing algorithm to verify any signature and (experimentally) sign payload using the miner's private key
269
166
 
270
167
  #### Symbols module (experimental)
271
168
 
272
- - `symbols.create(): symbolref` = create a unique reference that can be passed around
169
+ Create unique references that can be passed around
273
170
 
274
171
  #### References module (experimental)
275
172
 
276
- - `refs.numerize(ref: symbolref/blobref/packref): i32` = translate any reference into a unique private pointer that can be stored into data structures
277
-
278
- - `refs.denumerize(pointer: i32): symbolref/blobref/packref` = get the exact same reference back from your private pointer
173
+ Translate any reference into a unique private pointer that can be stored into data structures
279
174
 
280
175
  This can be useful if you want to check a reference for authenticity
281
176
 
@@ -0,0 +1,13 @@
1
+ import type { Cursor } from "@hazae41/cursor";
2
+ export type Packable = null | number | Uint8Array | string | bigint | Array<Packable>;
3
+ export declare class Packed {
4
+ readonly value: Packable;
5
+ constructor(value: Packable);
6
+ sizeOrThrow(): number;
7
+ writeOrThrow(cursor: Cursor): void;
8
+ }
9
+ export declare namespace Packed {
10
+ function readOrThrow(cursor: Cursor): Packable;
11
+ function sizeOrThrow(value: Packable): number;
12
+ function writeOrThrow(value: Packable, cursor: Cursor): void;
13
+ }
@@ -0,0 +1,114 @@
1
+ // deno-lint-ignore-file no-namespace
2
+ export class Packed {
3
+ value;
4
+ constructor(value) {
5
+ this.value = value;
6
+ }
7
+ sizeOrThrow() {
8
+ return Packed.sizeOrThrow(this.value);
9
+ }
10
+ writeOrThrow(cursor) {
11
+ Packed.writeOrThrow(this.value, cursor);
12
+ }
13
+ }
14
+ (function (Packed) {
15
+ function readOrThrow(cursor) {
16
+ const type = cursor.readUint8OrThrow();
17
+ if (type === 0)
18
+ return null;
19
+ if (type === 1)
20
+ return cursor.readFloat64OrThrow(true);
21
+ if (type === 2)
22
+ return cursor.readOrThrow(cursor.readUint32OrThrow(true));
23
+ if (type === 3) {
24
+ const size = cursor.readUint32OrThrow(true);
25
+ const data = cursor.readOrThrow(size);
26
+ return new TextDecoder().decode(data);
27
+ }
28
+ if (type === 4) {
29
+ const negative = cursor.readUint8OrThrow();
30
+ const size = cursor.readUint32OrThrow(true);
31
+ const data = cursor.readOrThrow(size);
32
+ const absolute = BigInt("0x" + data.toHex());
33
+ return negative ? -absolute : absolute;
34
+ }
35
+ if (type === 5) {
36
+ const length = cursor.readUint32OrThrow(true);
37
+ const values = new Array(length);
38
+ for (let i = 0; i < length; i++)
39
+ values[i] = readOrThrow(cursor);
40
+ return values;
41
+ }
42
+ throw new Error("Unknown pack type");
43
+ }
44
+ Packed.readOrThrow = readOrThrow;
45
+ function sizeOrThrow(value) {
46
+ if (value == null)
47
+ return 1;
48
+ if (typeof value === "number")
49
+ return 1 + 4;
50
+ if (value instanceof Uint8Array)
51
+ return 1 + 4 + value.length;
52
+ if (typeof value === "string")
53
+ return 1 + 4 + new TextEncoder().encode(value).length;
54
+ if (typeof value === "bigint") {
55
+ const absolute = value < 0n ? -value : value;
56
+ const text = absolute.toString(16);
57
+ const data = Uint8Array.fromHex(text.length % 2 === 1 ? "0" + text : text);
58
+ return 1 + 1 + 4 + data.length;
59
+ }
60
+ if (Array.isArray(value)) {
61
+ let size = 0;
62
+ size += 1;
63
+ size += 4;
64
+ for (const subvalue of value)
65
+ size += sizeOrThrow(subvalue);
66
+ return size;
67
+ }
68
+ throw new Error("Unknown pack value");
69
+ }
70
+ Packed.sizeOrThrow = sizeOrThrow;
71
+ function writeOrThrow(value, cursor) {
72
+ if (value == null) {
73
+ cursor.writeUint8OrThrow(0);
74
+ return;
75
+ }
76
+ if (typeof value === "number") {
77
+ cursor.writeUint8OrThrow(1);
78
+ cursor.writeFloat64OrThrow(value, true);
79
+ return;
80
+ }
81
+ if (value instanceof Uint8Array) {
82
+ cursor.writeUint8OrThrow(2);
83
+ cursor.writeUint32OrThrow(value.length, true);
84
+ cursor.writeOrThrow(value);
85
+ return;
86
+ }
87
+ if (typeof value === "string") {
88
+ cursor.writeUint8OrThrow(3);
89
+ const data = new TextEncoder().encode(value);
90
+ cursor.writeUint32OrThrow(data.length, true);
91
+ cursor.writeOrThrow(data);
92
+ return;
93
+ }
94
+ if (typeof value === "bigint") {
95
+ cursor.writeUint8OrThrow(4);
96
+ const [negative, absolute] = value < 0n ? [1, -value] : [0, value];
97
+ const text = absolute.toString(16);
98
+ const data = Uint8Array.fromHex(text.length % 2 === 1 ? "0" + text : text);
99
+ cursor.writeUint8OrThrow(negative);
100
+ cursor.writeUint32OrThrow(data.length, true);
101
+ cursor.writeOrThrow(data);
102
+ return;
103
+ }
104
+ if (Array.isArray(value)) {
105
+ cursor.writeUint8OrThrow(5);
106
+ cursor.writeUint32OrThrow(value.length, true);
107
+ for (const subvalue of value)
108
+ writeOrThrow(subvalue, cursor);
109
+ return;
110
+ }
111
+ throw new Error("Unknown pack value");
112
+ }
113
+ Packed.writeOrThrow = writeOrThrow;
114
+ })(Packed || (Packed = {}));
@@ -10,10 +10,10 @@ self.addEventListener("message", async (event) => {
10
10
  const request = event.data;
11
11
  if (request.method === "storage_set") {
12
12
  return await runAsImmediateOrThrow(database, async (database) => {
13
- const [module, method, args, events] = event.data.params;
13
+ const [module, method, args, writes] = event.data.params;
14
14
  const moment = await database.prepare(`INSERT INTO moments (epoch, module, method, params) VALUES (0, ?, ?, ?);`).run(module, method, args);
15
15
  const writer = database.prepare(`INSERT INTO events (moment, module, key, value) VALUES (?, ?, ?, ?);`);
16
- for (const [module, key, value] of events)
16
+ for (const [module, key, value] of writes)
17
17
  await writer.run(moment.lastInsertRowid, module, key, value);
18
18
  request.result[0] = 1;
19
19
  request.result[1] = moment.lastInsertRowid;
@@ -58,7 +58,7 @@ import { connect } from "@tursodatabase/database";
58
58
  import { existsSync, mkdirSync, symlinkSync, writeFileSync } from "node:fs";
59
59
  import { dirname } from "node:path";
60
60
  import process from "node:process";
61
- import { Pack } from "../../libs/packs/mod.js";
61
+ import { Packed } from "../../libs/packed/mod.js";
62
62
  export async function serveWithEnv(prefix = "") {
63
63
  const { DATABASE_PATH = process.env[prefix + "DATABASE_PATH"], SCRIPTS_PATH = process.env[prefix + "SCRIPTS_PATH"], ED25519_PRIVATE_KEY_HEX = process.env[prefix + "ED25519_PRIVATE_KEY_HEX"], ED25519_PUBLIC_KEY_HEX = process.env[prefix + "ED25519_PUBLIC_KEY_HEX"], } = {};
64
64
  if (DATABASE_PATH == null)
@@ -92,7 +92,8 @@ export async function serve(config) {
92
92
 
93
93
  module TEXT NOT NULL,
94
94
 
95
- key BLOB NOT NULL,
95
+ key TEXT NOT NULL,
96
+
96
97
  value BLOB NOT NULL
97
98
  );`);
98
99
  await database.exec(`CREATE TABLE IF NOT EXISTS moments (
@@ -101,7 +102,9 @@ export async function serve(config) {
101
102
  epoch INTEGER NOT NULL,
102
103
 
103
104
  module TEXT NOT NULL,
105
+
104
106
  method TEXT NOT NULL,
107
+
105
108
  params BLOB NOT NULL
106
109
  );`);
107
110
  await database.close();
@@ -141,7 +144,7 @@ export async function serve(config) {
141
144
  const sparksAsBigInt = (2n ** 256n) / BigInt("0x" + new Uint8Array(await crypto.subtle.digest("SHA-256", effortAsBytes)).toHex());
142
145
  if (sparksAsBigInt < (wasmAsBytes.length + saltAsBytes.length))
143
146
  return Response.json(null, { status: 402 });
144
- const packAsBytes = Writable.writeToBytesOrThrow(new Pack([wasmAsBytes, saltAsBytes]));
147
+ const packAsBytes = Writable.writeToBytesOrThrow(new Packed([wasmAsBytes, saltAsBytes]));
145
148
  const digestOfWasmAsBytes = new Uint8Array(await crypto.subtle.digest("SHA-256", wasmAsBytes));
146
149
  const digestOfPackAsBytes = new Uint8Array(await crypto.subtle.digest("SHA-256", packAsBytes));
147
150
  const digestOfWasmAsHex = digestOfWasmAsBytes.toHex();
@@ -5,21 +5,21 @@ import * as Wasm from "@hazae41/wasm";
5
5
  import { Buffer } from "node:buffer";
6
6
  import { existsSync, readFileSync, symlinkSync, writeFileSync } from "node:fs";
7
7
  import { meter } from "../../libs/metering/mod.js";
8
- import { Pack } from "../../libs/packs/mod.js";
8
+ import { Packed } from "../../libs/packed/mod.js";
9
9
  const config = await fetch(self.name).then(res => res.json());
10
10
  const helper = new Worker(import.meta.resolve("../helper/bin.js"), { name: self.name, type: "module" });
11
11
  function run(module, method, params, mode, maxsparks) {
12
12
  let sparks = 0n;
13
13
  const exports = {};
14
- const caches = new Map();
15
14
  const logs = new Array();
15
+ const caches = new Map();
16
16
  const reads = new Array();
17
17
  const writes = new Array();
18
- const pack_encode = (pack) => {
19
- return Writable.writeToBytesOrThrow(new Pack(pack));
18
+ const pack_encode = (value) => {
19
+ return Writable.writeToBytesOrThrow(new Packed(value));
20
20
  };
21
21
  const pack_decode = (bytes) => {
22
- return Readable.readFromBytesOrThrow(Pack, bytes);
22
+ return Readable.readFromBytesOrThrow(Packed, bytes);
23
23
  };
24
24
  const sparks_consume = (amount) => {
25
25
  sparks += amount;
@@ -173,12 +173,6 @@ function run(module, method, params, mode, maxsparks) {
173
173
  if (value === undefined)
174
174
  throw new Error("Not found");
175
175
  return value;
176
- },
177
- encode: (pack) => {
178
- return pack_encode(pack);
179
- },
180
- decode: (blob) => {
181
- return pack_decode(blob);
182
176
  }
183
177
  };
184
178
  imports["bigints"] = {
@@ -239,14 +233,6 @@ function run(module, method, params, mode, maxsparks) {
239
233
  pow: (left, right) => {
240
234
  return left ** right;
241
235
  },
242
- encode: (bigint) => {
243
- const text = bigint.toString(16);
244
- const data = Uint8Array.fromHex(text.length % 2 === 1 ? "0" + text : text);
245
- return data;
246
- },
247
- decode: (bytes) => {
248
- return BigInt("0x" + bytes.toHex());
249
- },
250
236
  from_base16: (text) => {
251
237
  return BigInt("0x" + text);
252
238
  },
@@ -280,7 +266,7 @@ function run(module, method, params, mode, maxsparks) {
280
266
  load(moduleAsString);
281
267
  if (typeof exports[moduleAsString][methodAsString] !== "function")
282
268
  throw new Error("Not found");
283
- return new Pack([exports[moduleAsString][methodAsString](...paramsAsPack.values)]);
269
+ return exports[moduleAsString][methodAsString](...paramsAsPack);
284
270
  },
285
271
  load: (moduleAsBytes) => {
286
272
  return readFileSync(`${config.scripts.path}/${moduleAsBytes.toHex()}.wasm`);
@@ -290,9 +276,10 @@ function run(module, method, params, mode, maxsparks) {
290
276
  }
291
277
  };
292
278
  imports["storage"] = {
293
- set: (key, value) => {
279
+ set: (key, fresh) => {
294
280
  const cache = caches.get(module);
295
- cache.set(key, value);
281
+ cache.set(key, fresh);
282
+ const value = pack_encode(fresh);
296
283
  writes.push([module, key, value]);
297
284
  return;
298
285
  },
@@ -309,9 +296,10 @@ function run(module, method, params, mode, maxsparks) {
309
296
  throw new Error("Internal error");
310
297
  if (result[1] === 2)
311
298
  return null;
312
- const fresh = new Uint8Array(result.buffer, 4 + 4 + 4, result[2]).slice();
299
+ const value = new Uint8Array(result.buffer, 4 + 4 + 4, result[2]).slice();
300
+ const fresh = pack_decode(value);
313
301
  cache.set(key, fresh);
314
- reads.push([module, key, fresh]);
302
+ reads.push([module, key, value]);
315
303
  return fresh;
316
304
  }
317
305
  };
@@ -385,8 +373,11 @@ function run(module, method, params, mode, maxsparks) {
385
373
  const { instance } = load(module);
386
374
  if (typeof instance.exports[method] !== "function")
387
375
  throw new Error("Not found");
388
- const returned = [instance.exports[method](...pack_decode(params))];
389
- if (mode !== 2)
376
+ const args = pack_decode(params);
377
+ if (!Array.isArray(args))
378
+ throw new Error("Params is not an array");
379
+ const returned = instance.exports[method](...args);
380
+ if (mode !== 1)
390
381
  return pack_encode([logs, reads, writes, returned, sparks]);
391
382
  if (writes.length) {
392
383
  const result = new Int32Array(new SharedArrayBuffer(4 + 4));
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@hazae41/bobine",
4
- "version": "0.0.11",
4
+ "version": "0.0.13",
5
5
  "description": "A blockchain in your garage",
6
6
  "repository": "github:hazae41/bobine",
7
7
  "author": "hazae41",
@@ -1,13 +0,0 @@
1
- import type { Cursor } from "@hazae41/cursor";
2
- export declare class Pack {
3
- readonly values: Array<Pack.Value>;
4
- constructor(values: Array<Pack.Value>);
5
- sizeOrThrow(): number;
6
- writeOrThrow(cursor: Cursor): void;
7
- }
8
- export declare namespace Pack {
9
- type Value = null | number | Uint8Array | string | bigint | Array<Value>;
10
- function readOrThrow(cursor: Cursor): Array<Value>;
11
- function sizeOrThrow(values: Array<Value>): number;
12
- function writeOrThrow(values: Array<Value>, cursor: Cursor): void;
13
- }
@@ -1,139 +0,0 @@
1
- // deno-lint-ignore-file no-namespace
2
- export class Pack {
3
- values;
4
- constructor(values) {
5
- this.values = values;
6
- }
7
- sizeOrThrow() {
8
- return Pack.sizeOrThrow(this.values);
9
- }
10
- writeOrThrow(cursor) {
11
- Pack.writeOrThrow(this.values, cursor);
12
- }
13
- }
14
- (function (Pack) {
15
- function readOrThrow(cursor) {
16
- const values = [];
17
- while (true) {
18
- const type = cursor.readUint8OrThrow();
19
- if (type === 0)
20
- break;
21
- if (type === 1) {
22
- values.push(null);
23
- continue;
24
- }
25
- if (type === 2) {
26
- values.push(Pack.readOrThrow(cursor));
27
- continue;
28
- }
29
- if (type === 3) {
30
- values.push(cursor.readFloat64OrThrow(true));
31
- continue;
32
- }
33
- if (type === 4) {
34
- const size = cursor.readUint32OrThrow(true);
35
- values.push(cursor.readOrThrow(size));
36
- continue;
37
- }
38
- if (type === 5) {
39
- const size = cursor.readUint32OrThrow(true);
40
- const data = cursor.readOrThrow(size);
41
- values.push(new TextDecoder().decode(data));
42
- continue;
43
- }
44
- if (type === 6) {
45
- const negative = cursor.readUint8OrThrow();
46
- const size = cursor.readUint32OrThrow(true);
47
- const data = cursor.readOrThrow(size);
48
- const absolute = BigInt("0x" + data.toHex());
49
- values.push(negative ? -absolute : absolute);
50
- continue;
51
- }
52
- throw new Error("Unknown pack type");
53
- }
54
- return values;
55
- }
56
- Pack.readOrThrow = readOrThrow;
57
- function sizeOrThrow(values) {
58
- let size = 0;
59
- for (const value of values) {
60
- if (value == null) {
61
- size += 1;
62
- continue;
63
- }
64
- if (Array.isArray(value)) {
65
- size += 1 + sizeOrThrow(value);
66
- continue;
67
- }
68
- if (typeof value === "number") {
69
- size += 1 + 4;
70
- continue;
71
- }
72
- if (value instanceof Uint8Array) {
73
- size += 1 + 4 + value.length;
74
- continue;
75
- }
76
- if (typeof value === "string") {
77
- const data = new TextEncoder().encode(value);
78
- size += 1 + 4 + data.length;
79
- continue;
80
- }
81
- if (typeof value === "bigint") {
82
- const absolute = value < 0n ? -value : value;
83
- const text = absolute.toString(16);
84
- const data = Uint8Array.fromHex(text.length % 2 === 1 ? "0" + text : text);
85
- size += 1 + 1 + 4 + data.length;
86
- continue;
87
- }
88
- throw new Error("Unknown pack value");
89
- }
90
- size += 1;
91
- return size;
92
- }
93
- Pack.sizeOrThrow = sizeOrThrow;
94
- function writeOrThrow(values, cursor) {
95
- for (const value of values) {
96
- if (value == null) {
97
- cursor.writeUint8OrThrow(1);
98
- continue;
99
- }
100
- if (Array.isArray(value)) {
101
- cursor.writeUint8OrThrow(2);
102
- writeOrThrow(value, cursor);
103
- continue;
104
- }
105
- if (typeof value === "number") {
106
- cursor.writeUint8OrThrow(3);
107
- cursor.writeFloat64OrThrow(value, true);
108
- continue;
109
- }
110
- if (value instanceof Uint8Array) {
111
- cursor.writeUint8OrThrow(4);
112
- cursor.writeUint32OrThrow(value.length, true);
113
- cursor.writeOrThrow(value);
114
- continue;
115
- }
116
- if (typeof value === "string") {
117
- cursor.writeUint8OrThrow(5);
118
- const data = new TextEncoder().encode(value);
119
- cursor.writeUint32OrThrow(data.length, true);
120
- cursor.writeOrThrow(data);
121
- continue;
122
- }
123
- if (typeof value === "bigint") {
124
- cursor.writeUint8OrThrow(6);
125
- const [negative, absolute] = value < 0n ? [1, -value] : [0, value];
126
- const text = absolute.toString(16);
127
- const data = Uint8Array.fromHex(text.length % 2 === 1 ? "0" + text : text);
128
- cursor.writeUint8OrThrow(negative);
129
- cursor.writeUint32OrThrow(data.length, true);
130
- cursor.writeOrThrow(data);
131
- continue;
132
- }
133
- throw new Error("Unknown pack value");
134
- }
135
- cursor.writeUint8OrThrow(0);
136
- return;
137
- }
138
- Pack.writeOrThrow = writeOrThrow;
139
- })(Pack || (Pack = {}));