78 lines
2.5 KiB
TypeScript
78 lines
2.5 KiB
TypeScript
import { Handle, Ref } from './actor.js';
|
|
import { Attenuation, Pattern, Template } from './rewrite.js';
|
|
import { Record, Value } from '@preserves/core';
|
|
|
|
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<T extends object>() {
|
|
return {
|
|
Assert: Record.makeConstructor<{assertion: Value<T>, handle: Handle}, T>()(
|
|
_Assert, ['assertion', 'handle']),
|
|
Retract: Record.makeConstructor<{handle: Handle}, T>()(
|
|
_Retract, ['handle']),
|
|
Message: Record.makeConstructor<{body: Value<T>}, T>()(
|
|
_Message, ['body']),
|
|
Sync: Record.makeConstructor<{peer: T}, T>()(
|
|
_Sync, ['peer']),
|
|
};
|
|
}
|
|
|
|
export type EntityMessage<T extends object> =
|
|
| Record<typeof _Assert, [Value<T>, Handle], T>
|
|
| Record<typeof _Retract, [Handle], T>
|
|
| Record<typeof _Message, [Value<T>], T>
|
|
| Record<typeof _Sync, [T], T>;
|
|
|
|
export type TurnMessage<T extends object> = Array<[Oid, EntityMessage<T>]>;
|
|
|
|
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<WireRef>();
|
|
|
|
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<Array<[Value<WireRef>, Value<WireRef>]>>;
|
|
|
|
export function encodeAttenuation(a: Attenuation | undefined): EncodedAttenuation {
|
|
if (a === void 0) return [];
|
|
return a.map(s => s.map(({pattern, template}) => [
|
|
pattern as Value<WireRef>,
|
|
template as Value<WireRef>,
|
|
]));
|
|
}
|
|
|
|
export function decodeAttenuation(v: Array<Value<WireRef>>): 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,
|
|
};
|
|
});
|
|
});
|
|
}
|