@statewalker/webrun-streams 0.2.2 → 0.3.0

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/dist/index.js CHANGED
@@ -31,7 +31,7 @@ async function collectString(input) {
31
31
  //#endregion
32
32
  //#region src/duplex.ts
33
33
  /**
34
- * Thrown by `emulateMux` and adapters when the underlying transport closes
34
+ * Thrown by adapters when the underlying transport closes
35
35
  * while one or more `Duplex` calls are in flight. Consumers can catch by
36
36
  * `instanceof TransportClosedError` or by checking `error.name`.
37
37
  */
@@ -144,404 +144,6 @@ function newCreditGrantor(window, threshold = .5) {
144
144
  } };
145
145
  }
146
146
  //#endregion
147
- //#region src/uint32.ts
148
- /**
149
- * Credit payloads are a single big-endian uint32, matching the frame header's
150
- * byte order.
151
- *
152
- * Deliberately **not** re-exported from `index.ts`: this is an internal codec
153
- * for the `emulateMux` wire format, not a compatibility commitment. Tests
154
- * import it by path.
155
- */
156
- /** The largest credit a single frame can advertise or grant: 2^32 - 1. */
157
- const MAX_UINT32 = 4294967295;
158
- /**
159
- * Clamps rather than wraps. `n >>> 0` is the obvious spelling and it is wrong
160
- * here: 2^32 becomes **0**, so a 4 GiB window advertises *zero credit* and the
161
- * peer stalls forever with no error — the exact silent hang credit exists to
162
- * remove. 2^32 + 5 becomes 5, which looks like a working window and is worse.
163
- * Anything above the ceiling is advertised as the ceiling.
164
- */
165
- function encodeUint32(n) {
166
- const bytes = /* @__PURE__ */ new Uint8Array(4);
167
- const clamped = Number.isFinite(n) ? Math.min(MAX_UINT32, Math.max(0, Math.floor(n))) : 0;
168
- new DataView(bytes.buffer).setUint32(0, clamped, false);
169
- return bytes;
170
- }
171
- /**
172
- * Returns `undefined` rather than a garbage number when the payload is too
173
- * short, so a truncated frame — or one from a peer predating credit — is
174
- * detectable at the call site instead of silently granting nonsense.
175
- */
176
- function decodeUint32(bytes) {
177
- if (bytes.byteLength < 4) return void 0;
178
- return new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength).getUint32(0, false);
179
- }
180
- //#endregion
181
- //#region src/emulate-mux.ts
182
- const TYPE_OPEN = 1;
183
- const TYPE_DATA = 2;
184
- const TYPE_ACK = 3;
185
- const TYPE_END = 4;
186
- const TYPE_ERROR = 5;
187
- const TYPE_CLOSE = 6;
188
- const DEFAULT_MAX_STREAMS = 256;
189
- const DEFAULT_MTU = 65536;
190
- const DEFAULT_MAX_STREAM_BUFFER = 8388608;
191
- const textEncoder = new TextEncoder();
192
- const textDecoder = new TextDecoder();
193
- function emulateMux(channel, opts = {}) {
194
- const maxStreams = opts.maxStreams ?? DEFAULT_MAX_STREAMS;
195
- const mtu = opts.mtu ?? DEFAULT_MTU;
196
- const maxStreamBuffer = opts.maxStreamBuffer ?? DEFAULT_MAX_STREAM_BUFFER;
197
- if (!(maxStreamBuffer >= 1)) throw new RangeError(`emulateMux: maxStreamBuffer must be at least 1, got ${maxStreamBuffer}`);
198
- const side = opts.side ?? "initiator";
199
- const streams = /* @__PURE__ */ new Map();
200
- let nextLocalId = side === "initiator" ? 2 : 1;
201
- let handler = null;
202
- let muxClosed = false;
203
- const sendFrame = (id, type, payload) => {
204
- if (muxClosed) return;
205
- const idEnc = encodeVarint(id);
206
- const total = idEnc.length + 1 + (payload?.byteLength ?? 0);
207
- const frame = new Uint8Array(total);
208
- frame.set(idEnc, 0);
209
- frame[idEnc.length] = type;
210
- if (payload && payload.byteLength > 0) frame.set(payload, idEnc.length + 1);
211
- try {
212
- channel.send(frame);
213
- } catch {}
214
- };
215
- const teardownStream = (s, err) => {
216
- if (s.closed) return;
217
- s.closed = true;
218
- s.outboundCredit.fail(err ?? new TransportClosedError("emulateMux: stream closed"));
219
- s.doneIn(err);
220
- s.cancelInput?.();
221
- streams.delete(s.id);
222
- };
223
- /**
224
- * Graceful counterpart to `teardownStream`. A stream occupies a slot in
225
- * `streams` until BOTH directions finish; releasing on inbound END alone
226
- * would set `closed` while our own `pumpOutbound` is still sending, and it
227
- * checks that flag to decide whether to keep going.
228
- *
229
- * Without this, only abnormal endings (cancel, ERROR, CLOSE, transport
230
- * failure) ever freed a slot, so every normally-completed call leaked one
231
- * until `maxStreams` began rejecting new calls.
232
- */
233
- const releaseIfComplete = (s) => {
234
- if (s.closed || !s.inDone || !s.outDone) return;
235
- s.closed = true;
236
- streams.delete(s.id);
237
- };
238
- const failAll = (err) => {
239
- if (muxClosed) return;
240
- muxClosed = true;
241
- for (const s of [...streams.values()]) teardownStream(s, err);
242
- streams.clear();
243
- };
244
- const createStream = (id) => {
245
- const queue = makeInboundQueue();
246
- const state = {
247
- id,
248
- inbound: queue.generator(() => {
249
- if (!state.closed && !muxClosed) sendFrame(state.id, TYPE_CLOSE);
250
- teardownStream(state);
251
- }),
252
- pushIn: queue.push,
253
- doneIn: queue.done,
254
- outboundCredit: newCreditLedger(0),
255
- grantor: newCreditGrantor(maxStreamBuffer),
256
- closed: false,
257
- inDone: false,
258
- outDone: false,
259
- queuedBytes: 0
260
- };
261
- return state;
262
- };
263
- const pumpOutbound = async (s, input) => {
264
- const iterator = input[Symbol.asyncIterator]?.() ?? input[Symbol.iterator]();
265
- s.cancelInput = () => {
266
- iterator.return?.(void 0);
267
- };
268
- try {
269
- for (;;) {
270
- const next = await iterator.next();
271
- if (next.done === true) break;
272
- const chunk = next.value;
273
- if (s.closed || muxClosed) return;
274
- if (chunk.byteLength === 0) continue;
275
- let off = 0;
276
- while (off < chunk.byteLength) {
277
- if (s.closed || muxClosed) return;
278
- const take = await s.outboundCredit.reserve(Math.min(mtu, chunk.byteLength - off));
279
- if (s.closed || muxClosed) return;
280
- const end = off + take;
281
- sendFrame(s.id, TYPE_DATA, chunk.subarray(off, end));
282
- off = end;
283
- }
284
- }
285
- if (!s.closed && !muxClosed) {
286
- sendFrame(s.id, TYPE_END);
287
- s.outDone = true;
288
- releaseIfComplete(s);
289
- }
290
- } catch (err) {
291
- if (!s.closed && !muxClosed) {
292
- const e = err instanceof Error ? err : new Error(String(err));
293
- sendFrame(s.id, TYPE_ERROR, encodeError(e));
294
- teardownStream(s, e);
295
- }
296
- }
297
- };
298
- const runHandler = async (s, h) => {
299
- let outbound;
300
- try {
301
- outbound = h(s.inbound);
302
- } catch (err) {
303
- const e = err instanceof Error ? err : new Error(String(err));
304
- sendFrame(s.id, TYPE_ERROR, encodeError(e));
305
- teardownStream(s, e);
306
- return;
307
- }
308
- await pumpOutbound(s, outbound);
309
- if (!s.inDone && !s.closed && !muxClosed) {
310
- sendFrame(s.id, TYPE_CLOSE);
311
- teardownStream(s);
312
- }
313
- };
314
- const handleFrame = (frame) => {
315
- if (muxClosed) return;
316
- if (frame.byteLength < 2) return;
317
- let id;
318
- let offset;
319
- try {
320
- ({value: id, offset} = decodeVarint(frame, 0));
321
- } catch {
322
- return;
323
- }
324
- if (offset >= frame.byteLength) return;
325
- const type = frame[offset];
326
- const payload = frame.subarray(offset + 1);
327
- if (type === TYPE_OPEN) {
328
- if (streams.has(id)) return;
329
- if (streams.size >= maxStreams) {
330
- sendFrame(id, TYPE_ERROR, encodeError(/* @__PURE__ */ new RangeError(`emulateMux: maxStreams=${maxStreams} exceeded`)));
331
- return;
332
- }
333
- if (!handler) {
334
- sendFrame(id, TYPE_ERROR, encodeError(/* @__PURE__ */ new Error("emulateMux: no handler registered")));
335
- return;
336
- }
337
- const s = createStream(id);
338
- streams.set(id, s);
339
- const advertised = decodeUint32(payload);
340
- if (advertised !== void 0) s.outboundCredit.grant(advertised);
341
- sendFrame(id, TYPE_ACK, encodeUint32(maxStreamBuffer));
342
- runHandler(s, handler);
343
- return;
344
- }
345
- const s = streams.get(id);
346
- if (!s) return;
347
- switch (type) {
348
- case TYPE_DATA: {
349
- s.queuedBytes += payload.byteLength;
350
- if (s.queuedBytes > maxStreamBuffer) {
351
- const err = /* @__PURE__ */ new RangeError(`emulateMux: stream ${id} buffered ${s.queuedBytes} bytes past maxStreamBuffer=${maxStreamBuffer} without being drained`);
352
- sendFrame(id, TYPE_ERROR, encodeError(err));
353
- teardownStream(s, err);
354
- return;
355
- }
356
- const copy = payload.byteLength === 0 ? payload : new Uint8Array(payload);
357
- s.pushIn(copy).then((handled) => {
358
- s.queuedBytes -= copy.byteLength;
359
- if (!handled || s.closed || muxClosed) return;
360
- const grant = s.grantor.consumed(copy.byteLength, s.queuedBytes === 0);
361
- if (grant > 0) sendFrame(id, TYPE_ACK, encodeUint32(grant));
362
- });
363
- return;
364
- }
365
- case TYPE_ACK: {
366
- const granted = decodeUint32(payload);
367
- if (granted !== void 0) s.outboundCredit.grant(granted);
368
- return;
369
- }
370
- case TYPE_END:
371
- s.inDone = true;
372
- s.doneIn();
373
- releaseIfComplete(s);
374
- return;
375
- case TYPE_ERROR:
376
- teardownStream(s, decodeError(payload));
377
- return;
378
- case TYPE_CLOSE:
379
- teardownStream(s);
380
- return;
381
- default: return;
382
- }
383
- };
384
- (async () => {
385
- try {
386
- for await (const frame of channel.recv) {
387
- if (muxClosed) break;
388
- handleFrame(frame);
389
- }
390
- } catch (err) {
391
- failAll(err instanceof Error ? err : new Error(String(err)));
392
- return;
393
- }
394
- failAll(new TransportClosedError());
395
- })();
396
- channel.closed.then(() => failAll(new TransportClosedError())).catch(() => {});
397
- const call = (input) => {
398
- if (muxClosed) return failedGenerator(new TransportClosedError());
399
- if (streams.size >= maxStreams) return failedGenerator(/* @__PURE__ */ new RangeError(`emulateMux: maxStreams=${maxStreams} exceeded`));
400
- const id = nextLocalId;
401
- nextLocalId += 2;
402
- const s = createStream(id);
403
- streams.set(id, s);
404
- sendFrame(id, TYPE_OPEN, encodeUint32(maxStreamBuffer));
405
- pumpOutbound(s, input);
406
- return s.inbound;
407
- };
408
- const serve = (h) => {
409
- handler = h;
410
- let torn = false;
411
- return async () => {
412
- if (torn) return;
413
- torn = true;
414
- if (handler === h) handler = null;
415
- };
416
- };
417
- const close = async () => {
418
- if (muxClosed) return;
419
- failAll(new TransportClosedError());
420
- try {
421
- channel.close();
422
- } catch {}
423
- };
424
- return {
425
- call,
426
- serve,
427
- close
428
- };
429
- }
430
- function failedGenerator(err) {
431
- return (async function* () {
432
- throw err;
433
- })();
434
- }
435
- /**
436
- * Push/pull queue with eager push/done handles. Unlike `newAsyncGenerator`, the
437
- * push and done functions are usable *before* the consumer begins iterating —
438
- * `emulateMux` needs to enqueue frames from inbound traffic regardless of when
439
- * (or whether) the consumer pulls them.
440
- *
441
- * `onCancel` fires only when the consumer terminates the generator before
442
- * `done()` was called — i.e., a unilateral cancellation. If `done()` is
443
- * called first (peer END/ERROR/CLOSE), the generator ends naturally and
444
- * `onCancel` does not fire.
445
- */
446
- function makeInboundQueue() {
447
- const slots = [];
448
- let wake = null;
449
- let queueClosed = false;
450
- let doneCalled = false;
451
- const push = (chunk) => {
452
- if (queueClosed) return Promise.resolve(false);
453
- return new Promise((resolve) => {
454
- slots.push({
455
- type: "value",
456
- value: chunk,
457
- resolve
458
- });
459
- wake?.();
460
- });
461
- };
462
- const done = (err) => {
463
- if (queueClosed || doneCalled) return Promise.resolve(false);
464
- doneCalled = true;
465
- return new Promise((resolve) => {
466
- slots.push({
467
- type: "done",
468
- err,
469
- resolve
470
- });
471
- wake?.();
472
- });
473
- };
474
- async function* generator(onCancel) {
475
- try {
476
- while (true) {
477
- if (slots.length === 0) {
478
- await new Promise((r) => {
479
- wake = r;
480
- });
481
- wake = null;
482
- continue;
483
- }
484
- const slot = slots.shift();
485
- if (slot.type === "done") {
486
- slot.resolve(true);
487
- if (slot.err) throw slot.err;
488
- return;
489
- }
490
- yield slot.value;
491
- slot.resolve(true);
492
- }
493
- } finally {
494
- queueClosed = true;
495
- for (const s of slots) s.resolve(false);
496
- slots.length = 0;
497
- if (!doneCalled) onCancel();
498
- }
499
- }
500
- return {
501
- generator,
502
- push,
503
- done
504
- };
505
- }
506
- function encodeVarint(value) {
507
- if (!Number.isInteger(value) || value < 0) throw new RangeError(`encodeVarint: ${value} is not a non-negative integer`);
508
- const out = [];
509
- let v = value;
510
- while (v >= 128) {
511
- out.push(v & 127 | 128);
512
- v >>>= 7;
513
- }
514
- out.push(v & 127);
515
- return new Uint8Array(out);
516
- }
517
- function decodeVarint(buf, start) {
518
- let value = 0;
519
- let shift = 0;
520
- let i = start;
521
- while (i < buf.length) {
522
- const b = buf[i++];
523
- value |= (b & 127) << shift;
524
- if ((b & 128) === 0) return {
525
- value: value >>> 0,
526
- offset: i
527
- };
528
- shift += 7;
529
- if (shift > 28) throw new Error("decodeVarint: too long");
530
- }
531
- throw new Error("decodeVarint: truncated");
532
- }
533
- function encodeError(err) {
534
- return textEncoder.encode(JSON.stringify(serializeError(err)));
535
- }
536
- function decodeError(buf) {
537
- if (buf.byteLength === 0) return /* @__PURE__ */ new Error("unknown stream error");
538
- try {
539
- return deserializeError(JSON.parse(textDecoder.decode(buf)));
540
- } catch {
541
- return new Error(textDecoder.decode(buf));
542
- }
543
- }
544
- //#endregion
545
147
  //#region src/lines.ts
546
148
  /** Split a stream of string chunks into individual lines (delimited by \n). */
547
149
  async function* splitLines(input) {
@@ -736,7 +338,7 @@ async function* newAsyncGenerator(init, skipValues = false) {
736
338
  }
737
339
  //#endregion
738
340
  //#region src/normalize.ts
739
- const utf8 = new TextEncoder();
341
+ const utf8 = /* @__PURE__ */ new TextEncoder();
740
342
  /**
741
343
  * Coerce common byte-like inputs into a `Uint8Array`. Strings encode as UTF-8.
742
344
  * Blobs return a `Promise<Uint8Array>`; every other input returns synchronously.
@@ -914,4 +516,4 @@ function toChunks(size = DEFAULT_CHUNK_SIZE) {
914
516
  };
915
517
  }
916
518
  //#endregion
917
- export { TransportClosedError, collect, collectBytes, collectString, decodeJsonl, decodeText, deserializeError, emulateMux, encodeJsonl, encodeText, fromReadableStream, joinLines, map, newAsyncGenerator, newCreditGrantor, newCreditLedger, normalizeToUint8Array, recieveIterator, sendIterator, serializeError, splitLines, toChunks, toReadableStream };
519
+ export { TransportClosedError, collect, collectBytes, collectString, decodeJsonl, decodeText, deserializeError, encodeJsonl, encodeText, fromReadableStream, joinLines, map, newAsyncGenerator, newCreditGrantor, newCreditLedger, normalizeToUint8Array, recieveIterator, sendIterator, serializeError, splitLines, toChunks, toReadableStream };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@statewalker/webrun-streams",
3
- "version": "0.2.2",
3
+ "version": "0.3.0",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "Async-iterator / ReadableStream primitives: collect, text/jsonl codecs, lines, backpressure generators, serialisable errors.",
@@ -35,7 +35,7 @@
35
35
  "rimraf": "^6.1.3",
36
36
  "rolldown": "^1.2.12",
37
37
  "typescript": "^7.0.2",
38
- "vitest": "^5.0.3"
38
+ "vitest": "^5.0.5"
39
39
  },
40
40
  "sideEffects": false,
41
41
  "publishConfig": {
package/src/duplex.ts CHANGED
@@ -47,7 +47,7 @@ export type Connect<P> = (params: P) => Promise<{
47
47
  export type Serve<P> = (params: P, handler: Duplex) => Promise<() => Promise<void>>;
48
48
 
49
49
  /**
50
- * Thrown by `emulateMux` and adapters when the underlying transport closes
50
+ * Thrown by adapters when the underlying transport closes
51
51
  * while one or more `Duplex` calls are in flight. Consumers can catch by
52
52
  * `instanceof TransportClosedError` or by checking `error.name`.
53
53
  */
@@ -11,10 +11,13 @@
11
11
  * offer: the receiver's capacity is not knowable to the sender unless the
12
12
  * receiver states it.
13
13
  *
14
- * **The unit is opaque.** This module never interprets the numbers it counts.
15
- * `emulateMux` passes byte counts and advertises `maxStreamBuffer`; the RPC
16
- * tier passes 1 per value and advertises a maximum in-flight value count.
17
- * Nothing here depends on which.
14
+ * **The unit is opaque.** This module never interprets the numbers it counts:
15
+ * bytes or values, it does not depend on which.
16
+ *
17
+ * **Dormant.** Its consumer, `emulateMux`, was removed in Plan C3, and
18
+ * `webrun-rpc`'s port stack keeps its own window. It stays exported and
19
+ * tested as the mechanism for per-stream windowing (spec D13) rather than be
20
+ * rewritten later.
18
21
  */
19
22
 
20
23
  export interface CreditLedger {
package/src/index.ts CHANGED
@@ -1,6 +1,5 @@
1
1
  export * from "./collect.js";
2
2
  export * from "./duplex.js";
3
- export * from "./emulate-mux.js";
4
3
  export * from "./errors.js";
5
4
  export * from "./flow-control.js";
6
5
  export * from "./jsonl.js";
package/src/normalize.ts CHANGED
@@ -1,4 +1,4 @@
1
- const utf8 = new TextEncoder();
1
+ const utf8 = /* @__PURE__ */ new TextEncoder();
2
2
 
3
3
  export type ByteLike = Uint8Array | ArrayBuffer | ArrayBufferView | Blob | string;
4
4
 
@@ -1,39 +0,0 @@
1
- import { type Duplex } from "./duplex.js";
2
- /**
3
- * The minimum a transport must expose to be wrapped by `emulateMux`. Inbound
4
- * bytes are surfaced as an async iterable; outbound is imperative `send`. All
5
- * five message-oriented transports (WebSocket, LiveKit data channel, PeerJS
6
- * DataConnection, MessagePort, in-process pipe) match this shape after a thin
7
- * wrapper.
8
- */
9
- export type ByteChannel = {
10
- send(bytes: Uint8Array): void;
11
- recv: AsyncIterable<Uint8Array>;
12
- closed: Promise<void>;
13
- close(): void;
14
- };
15
- export interface EmulateMuxOptions {
16
- maxStreams?: number;
17
- mtu?: number;
18
- /**
19
- * Cap on inbound bytes one stream may hold for a consumer that has not
20
- * drained them. Exceeding it tears down that stream alone.
21
- *
22
- * It is also the credit this side advertises to the peer, so it must be at
23
- * least 1 — a window of 0 authorises nothing and hangs the peer forever —
24
- * and it travels in a uint32, so a value above `MAX_UINT32` (4 GiB - 1) is
25
- * advertised as `MAX_UINT32`.
26
- */
27
- maxStreamBuffer?: number;
28
- /**
29
- * Stream-id allocation side. Initiator uses even ids (2, 4, …); responder
30
- * uses odd ids (1, 3, …). Pick one per peer so allocations don't collide.
31
- */
32
- side?: "initiator" | "responder";
33
- }
34
- export declare function emulateMux(channel: ByteChannel, opts?: EmulateMuxOptions): {
35
- call: Duplex;
36
- serve: (handler: Duplex) => () => Promise<void>;
37
- close: () => Promise<void>;
38
- };
39
- //# sourceMappingURL=emulate-mux.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"emulate-mux.d.ts","sourceRoot":"","sources":["../src/emulate-mux.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,MAAM,EAAwB,MAAM,aAAa,CAAC;AAUhE;;;;;;GAMG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,CAAC;IAC9B,IAAI,EAAE,aAAa,CAAC,UAAU,CAAC,CAAC;IAChC,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IACtB,KAAK,IAAI,IAAI,CAAC;CACf,CAAC;AA4CF,MAAM,WAAW,iBAAiB;IAChC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;;;;;;OAQG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;OAGG;IACH,IAAI,CAAC,EAAE,WAAW,GAAG,WAAW,CAAC;CAClC;AAED,wBAAgB,UAAU,CACxB,OAAO,EAAE,WAAW,EACpB,IAAI,GAAE,iBAAsB,GAC3B;IACD,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAChD,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5B,CAuVA"}
package/dist/uint32.d.ts DELETED
@@ -1,25 +0,0 @@
1
- /**
2
- * Credit payloads are a single big-endian uint32, matching the frame header's
3
- * byte order.
4
- *
5
- * Deliberately **not** re-exported from `index.ts`: this is an internal codec
6
- * for the `emulateMux` wire format, not a compatibility commitment. Tests
7
- * import it by path.
8
- */
9
- /** The largest credit a single frame can advertise or grant: 2^32 - 1. */
10
- export declare const MAX_UINT32 = 4294967295;
11
- /**
12
- * Clamps rather than wraps. `n >>> 0` is the obvious spelling and it is wrong
13
- * here: 2^32 becomes **0**, so a 4 GiB window advertises *zero credit* and the
14
- * peer stalls forever with no error — the exact silent hang credit exists to
15
- * remove. 2^32 + 5 becomes 5, which looks like a working window and is worse.
16
- * Anything above the ceiling is advertised as the ceiling.
17
- */
18
- export declare function encodeUint32(n: number): Uint8Array;
19
- /**
20
- * Returns `undefined` rather than a garbage number when the payload is too
21
- * short, so a truncated frame — or one from a peer predating credit — is
22
- * detectable at the call site instead of silently granting nonsense.
23
- */
24
- export declare function decodeUint32(bytes: Uint8Array): number | undefined;
25
- //# sourceMappingURL=uint32.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"uint32.d.ts","sourceRoot":"","sources":["../src/uint32.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,0EAA0E;AAC1E,eAAO,MAAM,UAAU,aAAa,CAAC;AAErC;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,GAAG,UAAU,CAKlD;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,GAAG,SAAS,CAGlE"}