tricu

A lazy functional language based on Tree Calculus
Log | Files | Refs | README | LICENSE

io-protocol.ts (3536B)


      1 // Inert wire decoding, not execution, resolution or a capability declaration.
      2 // The caller retains the action and returned borrowed handles across collection.
      3 export type Node<H> = { kind: 'leaf' } | { kind: 'stem'; child: H } | { kind: 'fork'; left: H; right: H };
      4 export interface Reader<H> { observe(handle: H): { node: Node<H> }; }
      5 export type Action<H> = { kind: 'core'; code: number; payload: H }
      6   | { kind: 'request'; group: string; revision: number; operation: string; arguments: H };
      7 
      8 export function canonicalNat<H>(reader: Reader<H>, handle: H, bits: number): bigint | undefined {
      9   if (!Number.isInteger(bits) || bits < 0 || bits > 64) throw new Error('Invalid natural bit bound');
     10   let rest = handle, value = 0n, count = 0, last = 0n;
     11   for (;;) {
     12     const node = reader.observe(rest).node;
     13     if (node.kind === 'leaf') return count === 0 || last === 1n ? value : undefined;
     14     if (count === bits || node.kind !== 'fork') return undefined;
     15     const bit = reader.observe(node.left).node;
     16     if (bit.kind === 'leaf') last = 0n;
     17     else if (bit.kind === 'stem' && reader.observe(bit.child).node.kind === 'leaf') last = 1n;
     18     else return undefined;
     19     value |= last << BigInt(count++); rest = node.right;
     20   }
     21 }
     22 function name<H>(reader: Reader<H>, handle: H): string | undefined {
     23   let rest = handle, value = '';
     24   for (;;) {
     25     const node = reader.observe(rest).node;
     26     if (node.kind === 'leaf') return value || undefined;
     27     // Observe only the excess spine cell, never its head or tail.
     28     if (value.length === 64 || node.kind !== 'fork') return undefined;
     29     const code = canonicalNat(reader, node.left, 7);
     30     if (code === undefined || !(code >= 97n && code <= 122n || value.length > 0 && (code >= 48n && code <= 57n || code === 45n))) return undefined;
     31     value += String.fromCharCode(Number(code)); rest = node.right;
     32   }
     33 }
     34 export class ProtocolError extends Error {}
     35 export function decodeAction<H>(reader: Reader<H>, handle: H): Action<H> {
     36   const action = reader.observe(handle).node;
     37   if (action.kind !== 'fork') throw new ProtocolError('invalid computation shape');
     38   const code = canonicalNat(reader, action.left, 8);
     39   if (code !== undefined && code <= 9n) return { kind: 'core', code: Number(code), payload: action.right };
     40   if (code !== 10n) throw new ProtocolError('unknown computation constructor');
     41   const group = reader.observe(action.right).node;
     42   if (group.kind !== 'fork') throw new ProtocolError('invalid facility header');
     43   const revision = reader.observe(group.right).node;
     44   if (revision.kind !== 'fork') throw new ProtocolError('invalid facility header');
     45   const operation = reader.observe(revision.right).node;
     46   if (operation.kind !== 'fork') throw new ProtocolError('invalid facility header');
     47   const g = name(reader, group.left);
     48   if (g === undefined) throw new ProtocolError('invalid facility header');
     49   const v = canonicalNat(reader, revision.left, 16);
     50   if (v === undefined || v === 0n) throw new ProtocolError('invalid facility header');
     51   const op = name(reader, operation.left);
     52   if (op === undefined) throw new ProtocolError('invalid facility header');
     53   return { kind: 'request', group: g, revision: Number(v), operation: op, arguments: operation.right };
     54 }
     55 export function header<H>(reader: Reader<H>, handle: H): object {
     56   const action = decodeAction(reader, handle);
     57   return action.kind === 'core' ? { kind: action.kind, code: action.code }
     58     : { kind: action.kind, group: action.group, revision: action.revision, operation: action.operation };
     59 }