import { Handle, Ref } from './actor.js'; import { Attenuation, Pattern, Template } from './rewrite.js'; import { Record, Value } from 'preserves'; export const _Assert = Symbol.for('assert'); export const _Retract = Symbol.for('retract'); export const _Message = Symbol.for('message'); export const _Sync = Symbol.for('sync'); function mk() { return { Assert: Record.makeConstructor<{assertion: Value, handle: Handle}, T>()( _Assert, ['assertion', 'handle']), Retract: Record.makeConstructor<{handle: Handle}, T>()( _Retract, ['handle']), Message: Record.makeConstructor<{body: Value}, T>()( _Message, ['body']), Sync: Record.makeConstructor<{peer: T}, T>()( _Sync, ['peer']), }; } export type EntityMessage = | Record, Handle], T> | Record | Record], T> | Record; export type TurnMessage = Array<[Oid, EntityMessage]>; export type Oid = number; export type WireSymbol = { oid: Oid, ref: Ref, count: number }; export type WireRef = | { loc: "mine", oid: Oid } | { loc: "your", oid: Oid, attenuation: EncodedAttenuation }; export const IO = mk(); export function myRef(oid: Oid): WireRef & { loc: "mine" } { return { loc: 'mine', oid }; } export function yourRef(oid: Oid, attenuation: EncodedAttenuation): WireRef & { loc: "your" } { return { loc: 'your', oid, attenuation }; } export type EncodedAttenuation = Array, Value]>>; export function encodeAttenuation(a: Attenuation | undefined): EncodedAttenuation { if (a === void 0) return []; return a.map(s => s.map(({pattern, template}) => [ pattern as Value, template as Value, ])); } export function decodeAttenuation(v: Array>): Attenuation { function complain(): never { throw new Error( `Received invalid attenuation ${v.asPreservesText()} from peer`); } if (v.length === 0) return []; return v.map(s => { if (!Array.isArray(s)) complain(); return s.map(e => { if (!(Array.isArray(e) && e.length === 2)) complain(); // TODO: check structure of pattern and template return { pattern: e[0] as Pattern, template: e[1] as Template, }; }); }); }