diff --git a/package.json b/package.json index 598b8ce..7edc8f5 100644 --- a/package.json +++ b/package.json @@ -6,8 +6,8 @@ "typescript": "^4.2.3" }, "dependencies": { - "@preserves/core": "^0.9.1", - "@preserves/schema": "^0.2.1" + "@preserves/core": "^0.10.0", + "@preserves/schema": "^0.3.1" }, "scripts": { "regenerate": "rm -rf ./src/gen && preserves-schema-ts --module Actor=./src/actor.ts --module Protocol=./src/protocol.ts --output ./src/gen './schemas/**/*.prs'", @@ -16,6 +16,7 @@ "compile:watch": "tsc -w", "rollup": "rollup -c", "rollup:watch": "rollup -c -w", - "clean": "rm -rf lib index.js" + "clean": "rm -rf lib index.js", + "build": "yarn regenerate && yarn compile && yarn rollup" } } diff --git a/src/actor.ts b/src/actor.ts index 3df38dc..63a9119 100644 --- a/src/actor.ts +++ b/src/actor.ts @@ -1,4 +1,4 @@ -import { IdentitySet, Value } from '@preserves/core'; +import { DecodeError, IdentitySet, TypedDecoder, Value } from '@preserves/core'; import { Attenuation, runRewrites } from './rewrite.js'; import { queueTask } from './task.js'; @@ -32,6 +32,10 @@ export function isRef(v: any): v is Ref { return 'relay' in v && v.relay instanceof Actor && 'target' in v; } +export function decodeRef(_d: TypedDecoder): Ref | undefined { + throw new DecodeError("Cannot decode Ref"); +} + let nextActorId = 0; export const __setNextActorId = (v: number) => nextActorId = v; diff --git a/src/gen/box-protocol.ts b/src/gen/box-protocol.ts index 8c96947..486369b 100644 --- a/src/gen/box-protocol.ts +++ b/src/gen/box-protocol.ts @@ -29,6 +29,23 @@ export function asBoxState(v: any): BoxState { if (!isBoxState(v)) {throw new TypeError(`Invalid BoxState: ${_.stringify(v)}`);} else {return v;}; } +export function decodeBoxState(d: _.TypedDecoder<_ptr>): BoxState | undefined { + return ((() => { + const M = d.mark(); + if (!d.openRecord()) return void 0; + const L = _.checkIs(d.nextSymbol(), $BoxState); + if (L === void 0) { d.restoreMark(M); return void 0; }; + const Fs = (((() => { + const M = d.mark(); + const v0 = d.nextSignedInteger(); if (v0 === void 0) { d.restoreMark(M); return void 0; }; + if (!d.closeCompound()) { d.restoreMark(M); return void 0; }; + return [v0] as [number]; + })())) as any; + if (Fs === void 0) { d.restoreMark(M); return void 0; }; + return _.Record<(typeof $BoxState), [number]>(L, Fs); + })()); +} + export function isSetBox(v: any): v is SetBox { return ( _.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v) && @@ -41,3 +58,22 @@ export function asSetBox(v: any): SetBox { if (!isSetBox(v)) {throw new TypeError(`Invalid SetBox: ${_.stringify(v)}`);} else {return v;}; } +export function decodeSetBox(d: _.TypedDecoder<_ptr>): SetBox | undefined { + return ((() => { + const M = d.mark(); + if (!d.openRecord()) return void 0; + const L = _.checkIs(d.nextSymbol(), $SetBox); + if (L === void 0) { d.restoreMark(M); return void 0; }; + const Fs = (((() => { + const M = d.mark(); + const v0 = d.nextSignedInteger(); if (v0 === void 0) { d.restoreMark(M); return void 0; }; + if (!d.closeCompound()) { d.restoreMark(M); return void 0; }; + return [v0] as [number]; + })())) as any; + if (Fs === void 0) { d.restoreMark(M); return void 0; }; + return _.Record<(typeof $SetBox), [number]>(L, Fs); + })()); +} + +export const _decodePtr = (d: _.TypedDecoder<_ptr>) => _i_Actor.decodeRef(d); + diff --git a/src/gen/dataspace.ts b/src/gen/dataspace.ts index 1b50993..d68cc50 100644 --- a/src/gen/dataspace.ts +++ b/src/gen/dataspace.ts @@ -24,3 +24,23 @@ export function asObserve(v: any): Observe { if (!isObserve(v)) {throw new TypeError(`Invalid Observe: ${_.stringify(v)}`);} else {return v;}; } +export function decodeObserve(d: _.TypedDecoder<_ptr>): Observe | undefined { + return ((() => { + const M = d.mark(); + if (!d.openRecord()) return void 0; + const L = _.checkIs(d.nextSymbol(), $Observe); + if (L === void 0) { d.restoreMark(M); return void 0; }; + const Fs = (((() => { + const M = d.mark(); + const v0 = d.nextSymbol(); if (v0 === void 0) { d.restoreMark(M); return void 0; }; + const v1 = _decodePtr(d); if (v1 === void 0) { d.restoreMark(M); return void 0; }; + if (!d.closeCompound()) { d.restoreMark(M); return void 0; }; + return [v0, v1] as [symbol, _ptr]; + })())) as any; + if (Fs === void 0) { d.restoreMark(M); return void 0; }; + return _.Record<(typeof $Observe), [symbol, _ptr]>(L, Fs); + })()); +} + +export const _decodePtr = (d: _.TypedDecoder<_ptr>) => _i_Actor.decodeRef(d); + diff --git a/src/gen/protocol.ts b/src/gen/protocol.ts index a4fa6d0..094fcb3 100644 --- a/src/gen/protocol.ts +++ b/src/gen/protocol.ts @@ -43,24 +43,34 @@ export function asAssertion(v: any): Assertion { if (!isAssertion(v)) {throw new TypeError(`Invalid Assertion: ${_.stringify(v)}`);} else {return v;}; } +export function decodeAssertion(d: _.TypedDecoder<_ptr>): Assertion | undefined {return d.next();} + export function isHandle(v: any): v is Handle {return typeof v === 'number';} export function asHandle(v: any): Handle { if (!isHandle(v)) {throw new TypeError(`Invalid Handle: ${_.stringify(v)}`);} else {return v;}; } +export function decodeHandle(d: _.TypedDecoder<_ptr>): Handle | undefined {return d.nextSignedInteger();} + export function isEvent(v: any): v is Event {return (isAssert(v) || isRetract(v) || isMessage(v) || isSync(v));} export function asEvent(v: any): Event { if (!isEvent(v)) {throw new TypeError(`Invalid Event: ${_.stringify(v)}`);} else {return v;}; } +export function decodeEvent(d: _.TypedDecoder<_ptr>): Event | undefined { + return (decodeAssert(d) ?? decodeRetract(d) ?? decodeMessage(d) ?? decodeSync(d)); +} + export function isOid(v: any): v is Oid {return typeof v === 'number';} export function asOid(v: any): Oid { if (!isOid(v)) {throw new TypeError(`Invalid Oid: ${_.stringify(v)}`);} else {return v;}; } +export function decodeOid(d: _.TypedDecoder<_ptr>): Oid | undefined {return d.nextSignedInteger();} + export function isTurn(v: any): v is Turn { return ( _.Array.isArray(v) && @@ -82,6 +92,25 @@ export function asTurn(v: any): Turn { if (!isTurn(v)) {throw new TypeError(`Invalid Turn: ${_.stringify(v)}`);} else {return v;}; } +export function decodeTurn(d: _.TypedDecoder<_ptr>): Turn | undefined { + return ((() => { + const M = d.mark(); + if (!d.openSequence()) return void 0; + const vN: Array<[Oid, Event]> = []; + let tmp: undefined | [Oid, Event]; + while ((tmp = ((() => { + const M = d.mark(); + if (!d.openSequence()) return void 0; + const v0 = decodeOid(d); if (v0 === void 0) { d.restoreMark(M); return void 0; }; + const v1 = decodeEvent(d); if (v1 === void 0) { d.restoreMark(M); return void 0; }; + if (!d.closeCompound()) { d.restoreMark(M); return void 0; }; + return [v0, v1] as [Oid, Event]; + })())) !== void 0) vN.push(tmp); + if (!d.closeCompound()) { d.restoreMark(M); return void 0; }; + return vN; + })()); +} + export function isAssert(v: any): v is Assert { return ( _.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v) && @@ -94,6 +123,24 @@ export function asAssert(v: any): Assert { if (!isAssert(v)) {throw new TypeError(`Invalid Assert: ${_.stringify(v)}`);} else {return v;}; } +export function decodeAssert(d: _.TypedDecoder<_ptr>): Assert | undefined { + return ((() => { + const M = d.mark(); + if (!d.openRecord()) return void 0; + const L = _.checkIs(d.nextSymbol(), $assert); + if (L === void 0) { d.restoreMark(M); return void 0; }; + const Fs = (((() => { + const M = d.mark(); + const v0 = decodeAssertion(d); if (v0 === void 0) { d.restoreMark(M); return void 0; }; + const v1 = decodeHandle(d); if (v1 === void 0) { d.restoreMark(M); return void 0; }; + if (!d.closeCompound()) { d.restoreMark(M); return void 0; }; + return [v0, v1] as [Assertion, Handle]; + })())) as any; + if (Fs === void 0) { d.restoreMark(M); return void 0; }; + return _.Record<(typeof $assert), [Assertion, Handle]>(L, Fs); + })()); +} + export function isRetract(v: any): v is Retract { return ( _.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v) && @@ -106,6 +153,23 @@ export function asRetract(v: any): Retract { if (!isRetract(v)) {throw new TypeError(`Invalid Retract: ${_.stringify(v)}`);} else {return v;}; } +export function decodeRetract(d: _.TypedDecoder<_ptr>): Retract | undefined { + return ((() => { + const M = d.mark(); + if (!d.openRecord()) return void 0; + const L = _.checkIs(d.nextSymbol(), $retract); + if (L === void 0) { d.restoreMark(M); return void 0; }; + const Fs = (((() => { + const M = d.mark(); + const v0 = decodeHandle(d); if (v0 === void 0) { d.restoreMark(M); return void 0; }; + if (!d.closeCompound()) { d.restoreMark(M); return void 0; }; + return [v0] as [Handle]; + })())) as any; + if (Fs === void 0) { d.restoreMark(M); return void 0; }; + return _.Record<(typeof $retract), [Handle]>(L, Fs); + })()); +} + export function isMessage(v: any): v is Message { return ( _.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v) && @@ -118,6 +182,23 @@ export function asMessage(v: any): Message { if (!isMessage(v)) {throw new TypeError(`Invalid Message: ${_.stringify(v)}`);} else {return v;}; } +export function decodeMessage(d: _.TypedDecoder<_ptr>): Message | undefined { + return ((() => { + const M = d.mark(); + if (!d.openRecord()) return void 0; + const L = _.checkIs(d.nextSymbol(), $message); + if (L === void 0) { d.restoreMark(M); return void 0; }; + const Fs = (((() => { + const M = d.mark(); + const v0 = decodeAssertion(d); if (v0 === void 0) { d.restoreMark(M); return void 0; }; + if (!d.closeCompound()) { d.restoreMark(M); return void 0; }; + return [v0] as [Assertion]; + })())) as any; + if (Fs === void 0) { d.restoreMark(M); return void 0; }; + return _.Record<(typeof $message), [Assertion]>(L, Fs); + })()); +} + export function isSync(v: any): v is Sync { return ( _.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v) && @@ -130,3 +211,22 @@ export function asSync(v: any): Sync { if (!isSync(v)) {throw new TypeError(`Invalid Sync: ${_.stringify(v)}`);} else {return v;}; } +export function decodeSync(d: _.TypedDecoder<_ptr>): Sync | undefined { + return ((() => { + const M = d.mark(); + if (!d.openRecord()) return void 0; + const L = _.checkIs(d.nextSymbol(), $sync); + if (L === void 0) { d.restoreMark(M); return void 0; }; + const Fs = (((() => { + const M = d.mark(); + const v0 = _decodePtr(d); if (v0 === void 0) { d.restoreMark(M); return void 0; }; + if (!d.closeCompound()) { d.restoreMark(M); return void 0; }; + return [v0] as [_ptr]; + })())) as any; + if (Fs === void 0) { d.restoreMark(M); return void 0; }; + return _.Record<(typeof $sync), [_ptr]>(L, Fs); + })()); +} + +export const _decodePtr = (d: _.TypedDecoder<_ptr>) => _i_Protocol.decodeWireRef(d); + diff --git a/src/gen/sturdy.ts b/src/gen/sturdy.ts index 8feb3f9..99ef414 100644 --- a/src/gen/sturdy.ts +++ b/src/gen/sturdy.ts @@ -120,6 +120,33 @@ export function asSturdyRef(v: any): SturdyRef { if (!isSturdyRef(v)) {throw new TypeError(`Invalid SturdyRef: ${_.stringify(v)}`);} else {return v;}; } +export function decodeSturdyRef(d: _.TypedDecoder<_ptr>): SturdyRef | undefined { + return ((() => { + const M = d.mark(); + if (!d.openRecord()) return void 0; + const L = _.checkIs(d.nextSymbol(), $ref); + if (L === void 0) { d.restoreMark(M); return void 0; }; + const Fs = (((() => { + const M = d.mark(); + const v0 = d.next(); if (v0 === void 0) { d.restoreMark(M); return void 0; }; + const v1 = ((() => { + const M = d.mark(); + if (!d.openSequence()) return void 0; + const vN: Array = []; + let tmp: undefined | Attenuation; + while ((tmp = decodeAttenuation(d)) !== void 0) vN.push(tmp); + if (!d.closeCompound()) { d.restoreMark(M); return void 0; }; + return vN; + })()); if (v1 === void 0) { d.restoreMark(M); return void 0; }; + const v2 = d.nextByteString(); if (v2 === void 0) { d.restoreMark(M); return void 0; }; + if (!d.closeCompound()) { d.restoreMark(M); return void 0; }; + return [v0, v1, v2] as [_val, Array, _.Bytes]; + })())) as any; + if (Fs === void 0) { d.restoreMark(M); return void 0; }; + return _.Record<(typeof $ref), [_val, Array, _.Bytes]>(L, Fs); + })()); +} + export function isAttenuation(v: any): v is Attenuation { return ( _.Array.isArray(v) && @@ -133,12 +160,26 @@ export function asAttenuation(v: any): Attenuation { if (!isAttenuation(v)) {throw new TypeError(`Invalid Attenuation: ${_.stringify(v)}`);} else {return v;}; } +export function decodeAttenuation(d: _.TypedDecoder<_ptr>): Attenuation | undefined { + return ((() => { + const M = d.mark(); + if (!d.openSequence()) return void 0; + const vN: Array = []; + let tmp: undefined | Caveat; + while ((tmp = decodeCaveat(d)) !== void 0) vN.push(tmp); + if (!d.closeCompound()) { d.restoreMark(M); return void 0; }; + return vN; + })()); +} + export function isCaveat(v: any): v is Caveat {return (isRewrite(v) || isAlts(v));} export function asCaveat(v: any): Caveat { if (!isCaveat(v)) {throw new TypeError(`Invalid Caveat: ${_.stringify(v)}`);} else {return v;}; } +export function decodeCaveat(d: _.TypedDecoder<_ptr>): Caveat | undefined {return (decodeRewrite(d) ?? decodeAlts(d));} + export function isRewrite(v: any): v is Rewrite { return ( _.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v) && @@ -151,6 +192,24 @@ export function asRewrite(v: any): Rewrite { if (!isRewrite(v)) {throw new TypeError(`Invalid Rewrite: ${_.stringify(v)}`);} else {return v;}; } +export function decodeRewrite(d: _.TypedDecoder<_ptr>): Rewrite | undefined { + return ((() => { + const M = d.mark(); + if (!d.openRecord()) return void 0; + const L = _.checkIs(d.nextSymbol(), $rewrite); + if (L === void 0) { d.restoreMark(M); return void 0; }; + const Fs = (((() => { + const M = d.mark(); + const v0 = decodePattern(d); if (v0 === void 0) { d.restoreMark(M); return void 0; }; + const v1 = decodeTemplate(d); if (v1 === void 0) { d.restoreMark(M); return void 0; }; + if (!d.closeCompound()) { d.restoreMark(M); return void 0; }; + return [v0, v1] as [Pattern, Template]; + })())) as any; + if (Fs === void 0) { d.restoreMark(M); return void 0; }; + return _.Record<(typeof $rewrite), [Pattern, Template]>(L, Fs); + })()); +} + export function isAlts(v: any): v is Alts { return ( _.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v) && @@ -171,6 +230,31 @@ export function asAlts(v: any): Alts { if (!isAlts(v)) {throw new TypeError(`Invalid Alts: ${_.stringify(v)}`);} else {return v;}; } +export function decodeAlts(d: _.TypedDecoder<_ptr>): Alts | undefined { + return ((() => { + const M = d.mark(); + if (!d.openRecord()) return void 0; + const L = _.checkIs(d.nextSymbol(), $or); + if (L === void 0) { d.restoreMark(M); return void 0; }; + const Fs = (((() => { + const M = d.mark(); + const v0 = ((() => { + const M = d.mark(); + if (!d.openSequence()) return void 0; + const vN: Array = []; + let tmp: undefined | Rewrite; + while ((tmp = decodeRewrite(d)) !== void 0) vN.push(tmp); + if (!d.closeCompound()) { d.restoreMark(M); return void 0; }; + return vN; + })()); if (v0 === void 0) { d.restoreMark(M); return void 0; }; + if (!d.closeCompound()) { d.restoreMark(M); return void 0; }; + return [v0] as [Array]; + })())) as any; + if (Fs === void 0) { d.restoreMark(M); return void 0; }; + return _.Record<(typeof $or), [Array]>(L, Fs); + })()); +} + export function isResolve(v: any): v is Resolve { return ( _.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v) && @@ -183,12 +267,32 @@ export function asResolve(v: any): Resolve { if (!isResolve(v)) {throw new TypeError(`Invalid Resolve: ${_.stringify(v)}`);} else {return v;}; } +export function decodeResolve(d: _.TypedDecoder<_ptr>): Resolve | undefined { + return ((() => { + const M = d.mark(); + if (!d.openRecord()) return void 0; + const L = _.checkIs(d.nextSymbol(), $resolve); + if (L === void 0) { d.restoreMark(M); return void 0; }; + const Fs = (((() => { + const M = d.mark(); + const v0 = decodeSturdyRef(d); if (v0 === void 0) { d.restoreMark(M); return void 0; }; + const v1 = _decodePtr(d); if (v1 === void 0) { d.restoreMark(M); return void 0; }; + if (!d.closeCompound()) { d.restoreMark(M); return void 0; }; + return [v0, v1] as [SturdyRef, _ptr]; + })())) as any; + if (Fs === void 0) { d.restoreMark(M); return void 0; }; + return _.Record<(typeof $resolve), [SturdyRef, _ptr]>(L, Fs); + })()); +} + export function isConstructorSpec(v: any): v is ConstructorSpec {return (isCRec(v) || isCArr(v) || isCDict(v));} export function asConstructorSpec(v: any): ConstructorSpec { if (!isConstructorSpec(v)) {throw new TypeError(`Invalid ConstructorSpec: ${_.stringify(v)}`);} else {return v;}; } +export function decodeConstructorSpec(d: _.TypedDecoder<_ptr>): ConstructorSpec | undefined {return (decodeCRec(d) ?? decodeCArr(d) ?? decodeCDict(d));} + export function isCRec(v: any): v is CRec { return ( _.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v) && @@ -201,6 +305,24 @@ export function asCRec(v: any): CRec { if (!isCRec(v)) {throw new TypeError(`Invalid CRec: ${_.stringify(v)}`);} else {return v;}; } +export function decodeCRec(d: _.TypedDecoder<_ptr>): CRec | undefined { + return ((() => { + const M = d.mark(); + if (!d.openRecord()) return void 0; + const L = _.checkIs(d.nextSymbol(), $rec); + if (L === void 0) { d.restoreMark(M); return void 0; }; + const Fs = (((() => { + const M = d.mark(); + const v0 = d.next(); if (v0 === void 0) { d.restoreMark(M); return void 0; }; + const v1 = d.nextSignedInteger(); if (v1 === void 0) { d.restoreMark(M); return void 0; }; + if (!d.closeCompound()) { d.restoreMark(M); return void 0; }; + return [v0, v1] as [_val, number]; + })())) as any; + if (Fs === void 0) { d.restoreMark(M); return void 0; }; + return _.Record<(typeof $rec), [_val, number]>(L, Fs); + })()); +} + export function isCArr(v: any): v is CArr { return ( _.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v) && @@ -213,6 +335,23 @@ export function asCArr(v: any): CArr { if (!isCArr(v)) {throw new TypeError(`Invalid CArr: ${_.stringify(v)}`);} else {return v;}; } +export function decodeCArr(d: _.TypedDecoder<_ptr>): CArr | undefined { + return ((() => { + const M = d.mark(); + if (!d.openRecord()) return void 0; + const L = _.checkIs(d.nextSymbol(), $arr); + if (L === void 0) { d.restoreMark(M); return void 0; }; + const Fs = (((() => { + const M = d.mark(); + const v0 = d.nextSignedInteger(); if (v0 === void 0) { d.restoreMark(M); return void 0; }; + if (!d.closeCompound()) { d.restoreMark(M); return void 0; }; + return [v0] as [number]; + })())) as any; + if (Fs === void 0) { d.restoreMark(M); return void 0; }; + return _.Record<(typeof $arr), [number]>(L, Fs); + })()); +} + export function isCDict(v: any): v is CDict { return ( _.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v) && @@ -225,6 +364,22 @@ export function asCDict(v: any): CDict { if (!isCDict(v)) {throw new TypeError(`Invalid CDict: ${_.stringify(v)}`);} else {return v;}; } +export function decodeCDict(d: _.TypedDecoder<_ptr>): CDict | undefined { + return ((() => { + const M = d.mark(); + if (!d.openRecord()) return void 0; + const L = _.checkIs(d.nextSymbol(), $dict); + if (L === void 0) { d.restoreMark(M); return void 0; }; + const Fs = (((() => { + const M = d.mark(); + if (!d.closeCompound()) { d.restoreMark(M); return void 0; }; + return [] as []; + })())) as any; + if (Fs === void 0) { d.restoreMark(M); return void 0; }; + return _.Record<(typeof $dict), []>(L, Fs); + })()); +} + export function isLit(v: any): v is Lit { return ( _.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v) && @@ -237,6 +392,23 @@ export function asLit(v: any): Lit { if (!isLit(v)) {throw new TypeError(`Invalid Lit: ${_.stringify(v)}`);} else {return v;}; } +export function decodeLit(d: _.TypedDecoder<_ptr>): Lit | undefined { + return ((() => { + const M = d.mark(); + if (!d.openRecord()) return void 0; + const L = _.checkIs(d.nextSymbol(), $lit); + if (L === void 0) { d.restoreMark(M); return void 0; }; + const Fs = (((() => { + const M = d.mark(); + const v0 = d.next(); if (v0 === void 0) { d.restoreMark(M); return void 0; }; + if (!d.closeCompound()) { d.restoreMark(M); return void 0; }; + return [v0] as [_val]; + })())) as any; + if (Fs === void 0) { d.restoreMark(M); return void 0; }; + return _.Record<(typeof $lit), [_val]>(L, Fs); + })()); +} + export function isPattern(v: any): v is Pattern { return ( isPDiscard(v) || @@ -252,6 +424,17 @@ export function asPattern(v: any): Pattern { if (!isPattern(v)) {throw new TypeError(`Invalid Pattern: ${_.stringify(v)}`);} else {return v;}; } +export function decodePattern(d: _.TypedDecoder<_ptr>): Pattern | undefined { + return ( + decodePDiscard(d) ?? + decodePBind(d) ?? + decodePAnd(d) ?? + decodePNot(d) ?? + decodeLit(d) ?? + decodePCompound(d) + ); +} + export function isPDiscard(v: any): v is PDiscard { return ( _.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v) && @@ -264,6 +447,22 @@ export function asPDiscard(v: any): PDiscard { if (!isPDiscard(v)) {throw new TypeError(`Invalid PDiscard: ${_.stringify(v)}`);} else {return v;}; } +export function decodePDiscard(d: _.TypedDecoder<_ptr>): PDiscard | undefined { + return ((() => { + const M = d.mark(); + if (!d.openRecord()) return void 0; + const L = _.checkIs(d.nextSymbol(), $__); + if (L === void 0) { d.restoreMark(M); return void 0; }; + const Fs = (((() => { + const M = d.mark(); + if (!d.closeCompound()) { d.restoreMark(M); return void 0; }; + return [] as []; + })())) as any; + if (Fs === void 0) { d.restoreMark(M); return void 0; }; + return _.Record<(typeof $__), []>(L, Fs); + })()); +} + export function isPBind(v: any): v is PBind { return ( _.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v) && @@ -276,6 +475,24 @@ export function asPBind(v: any): PBind { if (!isPBind(v)) {throw new TypeError(`Invalid PBind: ${_.stringify(v)}`);} else {return v;}; } +export function decodePBind(d: _.TypedDecoder<_ptr>): PBind | undefined { + return ((() => { + const M = d.mark(); + if (!d.openRecord()) return void 0; + const L = _.checkIs(d.nextSymbol(), $bind); + if (L === void 0) { d.restoreMark(M); return void 0; }; + const Fs = (((() => { + const M = d.mark(); + const v0 = d.nextSymbol(); if (v0 === void 0) { d.restoreMark(M); return void 0; }; + const v1 = decodePattern(d); if (v1 === void 0) { d.restoreMark(M); return void 0; }; + if (!d.closeCompound()) { d.restoreMark(M); return void 0; }; + return [v0, v1] as [symbol, Pattern]; + })())) as any; + if (Fs === void 0) { d.restoreMark(M); return void 0; }; + return _.Record<(typeof $bind), [symbol, Pattern]>(L, Fs); + })()); +} + export function isPAnd(v: any): v is PAnd { return ( _.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v) && @@ -296,6 +513,31 @@ export function asPAnd(v: any): PAnd { if (!isPAnd(v)) {throw new TypeError(`Invalid PAnd: ${_.stringify(v)}`);} else {return v;}; } +export function decodePAnd(d: _.TypedDecoder<_ptr>): PAnd | undefined { + return ((() => { + const M = d.mark(); + if (!d.openRecord()) return void 0; + const L = _.checkIs(d.nextSymbol(), $and); + if (L === void 0) { d.restoreMark(M); return void 0; }; + const Fs = (((() => { + const M = d.mark(); + const v0 = ((() => { + const M = d.mark(); + if (!d.openSequence()) return void 0; + const vN: Array = []; + let tmp: undefined | Pattern; + while ((tmp = decodePattern(d)) !== void 0) vN.push(tmp); + if (!d.closeCompound()) { d.restoreMark(M); return void 0; }; + return vN; + })()); if (v0 === void 0) { d.restoreMark(M); return void 0; }; + if (!d.closeCompound()) { d.restoreMark(M); return void 0; }; + return [v0] as [Array]; + })())) as any; + if (Fs === void 0) { d.restoreMark(M); return void 0; }; + return _.Record<(typeof $and), [Array]>(L, Fs); + })()); +} + export function isPNot(v: any): v is PNot { return ( _.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v) && @@ -308,6 +550,23 @@ export function asPNot(v: any): PNot { if (!isPNot(v)) {throw new TypeError(`Invalid PNot: ${_.stringify(v)}`);} else {return v;}; } +export function decodePNot(d: _.TypedDecoder<_ptr>): PNot | undefined { + return ((() => { + const M = d.mark(); + if (!d.openRecord()) return void 0; + const L = _.checkIs(d.nextSymbol(), $not); + if (L === void 0) { d.restoreMark(M); return void 0; }; + const Fs = (((() => { + const M = d.mark(); + const v0 = decodePattern(d); if (v0 === void 0) { d.restoreMark(M); return void 0; }; + if (!d.closeCompound()) { d.restoreMark(M); return void 0; }; + return [v0] as [Pattern]; + })())) as any; + if (Fs === void 0) { d.restoreMark(M); return void 0; }; + return _.Record<(typeof $not), [Pattern]>(L, Fs); + })()); +} + export function isPCompound(v: any): v is PCompound { return ( _.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v) && @@ -330,12 +589,44 @@ export function asPCompound(v: any): PCompound { if (!isPCompound(v)) {throw new TypeError(`Invalid PCompound: ${_.stringify(v)}`);} else {return v;}; } +export function decodePCompound(d: _.TypedDecoder<_ptr>): PCompound | undefined { + return ((() => { + const M = d.mark(); + if (!d.openRecord()) return void 0; + const L = _.checkIs(d.nextSymbol(), $compound); + if (L === void 0) { d.restoreMark(M); return void 0; }; + const Fs = (((() => { + const M = d.mark(); + const v0 = decodeConstructorSpec(d); if (v0 === void 0) { d.restoreMark(M); return void 0; }; + const v1 = ((() => { + const M = d.mark(); + if (!d.openDictionary()) return void 0; + const r: _.KeyedDictionary<_val, Pattern, _ptr> = new _.KeyedDictionary(); + let K: undefined | _val; + while ((K = d.next()) !== void 0) { + const V = decodePattern(d); + if (V === void 0) { d.restoreMark(M); return void 0; }; + r.set(K, V); + }; + if (!d.closeCompound()) { d.restoreMark(M); return void 0; }; + return r; + })()); if (v1 === void 0) { d.restoreMark(M); return void 0; }; + if (!d.closeCompound()) { d.restoreMark(M); return void 0; }; + return [v0, v1] as [ConstructorSpec, _.KeyedDictionary<_val, Pattern, _ptr>]; + })())) as any; + if (Fs === void 0) { d.restoreMark(M); return void 0; }; + return _.Record<(typeof $compound), [ConstructorSpec, _.KeyedDictionary<_val, Pattern, _ptr>]>(L, Fs); + })()); +} + export function isTemplate(v: any): v is Template {return (isTRef(v) || isLit(v) || isTCompound(v));} export function asTemplate(v: any): Template { if (!isTemplate(v)) {throw new TypeError(`Invalid Template: ${_.stringify(v)}`);} else {return v;}; } +export function decodeTemplate(d: _.TypedDecoder<_ptr>): Template | undefined {return (decodeTRef(d) ?? decodeLit(d) ?? decodeTCompound(d));} + export function isTRef(v: any): v is TRef { return ( _.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v) && @@ -348,6 +639,23 @@ export function asTRef(v: any): TRef { if (!isTRef(v)) {throw new TypeError(`Invalid TRef: ${_.stringify(v)}`);} else {return v;}; } +export function decodeTRef(d: _.TypedDecoder<_ptr>): TRef | undefined { + return ((() => { + const M = d.mark(); + if (!d.openRecord()) return void 0; + const L = _.checkIs(d.nextSymbol(), $ref); + if (L === void 0) { d.restoreMark(M); return void 0; }; + const Fs = (((() => { + const M = d.mark(); + const v0 = d.nextSymbol(); if (v0 === void 0) { d.restoreMark(M); return void 0; }; + if (!d.closeCompound()) { d.restoreMark(M); return void 0; }; + return [v0] as [symbol]; + })())) as any; + if (Fs === void 0) { d.restoreMark(M); return void 0; }; + return _.Record<(typeof $ref), [symbol]>(L, Fs); + })()); +} + export function isTCompound(v: any): v is TCompound { return ( _.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v) && @@ -370,3 +678,35 @@ export function asTCompound(v: any): TCompound { if (!isTCompound(v)) {throw new TypeError(`Invalid TCompound: ${_.stringify(v)}`);} else {return v;}; } +export function decodeTCompound(d: _.TypedDecoder<_ptr>): TCompound | undefined { + return ((() => { + const M = d.mark(); + if (!d.openRecord()) return void 0; + const L = _.checkIs(d.nextSymbol(), $compound); + if (L === void 0) { d.restoreMark(M); return void 0; }; + const Fs = (((() => { + const M = d.mark(); + const v0 = decodeConstructorSpec(d); if (v0 === void 0) { d.restoreMark(M); return void 0; }; + const v1 = ((() => { + const M = d.mark(); + if (!d.openDictionary()) return void 0; + const r: _.KeyedDictionary<_val, Template, _ptr> = new _.KeyedDictionary(); + let K: undefined | _val; + while ((K = d.next()) !== void 0) { + const V = decodeTemplate(d); + if (V === void 0) { d.restoreMark(M); return void 0; }; + r.set(K, V); + }; + if (!d.closeCompound()) { d.restoreMark(M); return void 0; }; + return r; + })()); if (v1 === void 0) { d.restoreMark(M); return void 0; }; + if (!d.closeCompound()) { d.restoreMark(M); return void 0; }; + return [v0, v1] as [ConstructorSpec, _.KeyedDictionary<_val, Template, _ptr>]; + })())) as any; + if (Fs === void 0) { d.restoreMark(M); return void 0; }; + return _.Record<(typeof $compound), [ConstructorSpec, _.KeyedDictionary<_val, Template, _ptr>]>(L, Fs); + })()); +} + +export const _decodePtr = (d: _.TypedDecoder<_ptr>) => _i_Actor.decodeRef(d); + diff --git a/src/gen/worker.ts b/src/gen/worker.ts index 678ff3f..c9f6825 100644 --- a/src/gen/worker.ts +++ b/src/gen/worker.ts @@ -23,3 +23,23 @@ export function asInstance(v: any): Instance { if (!isInstance(v)) {throw new TypeError(`Invalid Instance: ${_.stringify(v)}`);} else {return v;}; } +export function decodeInstance(d: _.TypedDecoder<_ptr>): Instance | undefined { + return ((() => { + const M = d.mark(); + if (!d.openRecord()) return void 0; + const L = _.checkIs(d.nextSymbol(), $Instance); + if (L === void 0) { d.restoreMark(M); return void 0; }; + const Fs = (((() => { + const M = d.mark(); + const v0 = d.nextString(); if (v0 === void 0) { d.restoreMark(M); return void 0; }; + const v1 = d.next(); if (v1 === void 0) { d.restoreMark(M); return void 0; }; + if (!d.closeCompound()) { d.restoreMark(M); return void 0; }; + return [v0, v1] as [string, _val]; + })())) as any; + if (Fs === void 0) { d.restoreMark(M); return void 0; }; + return _.Record<(typeof $Instance), [string, _val]>(L, Fs); + })()); +} + +export const _decodePtr = () => { throw new _.DecodeError("Pointers forbidden"); }; + diff --git a/src/protocol.ts b/src/protocol.ts index 2be3668..3ba1cda 100644 --- a/src/protocol.ts +++ b/src/protocol.ts @@ -1,6 +1,7 @@ -import { Attenuation } from './gen/sturdy.js'; +import { Attenuation, decodeAttenuation } from './gen/sturdy.js'; import * as IO from './gen/protocol.js'; -import { Ref } from './actor.js'; +import { decodeRef, Ref } from './actor.js'; +import { TypedDecoder } from '@preserves/core'; export type WireSymbol = { oid: IO.Oid, ref: Ref, count: number }; @@ -15,3 +16,36 @@ export function myRef(oid: IO.Oid): WireRef & { loc: "mine" } { export function yourRef(oid: IO.Oid, attenuation: Attenuation): WireRef & { loc: "your" } { return { loc: 'your', oid, attenuation }; } + +export function decodeWireRef(d: TypedDecoder): WireRef | undefined { + const M = d.mark(); + if (d.openSequence()) { + switch (d.nextSignedInteger()) { + case 0: { + const oid = d.nextSignedInteger(); + if (oid !== void 0) { + if (d.closeCompound()) { + return myRef(oid); + } + } + break; + } + case 1: { + const oid = d.nextSignedInteger(); + if (oid !== void 0) { + const attenuation = d.withPointerDecoder(decodeRef, d => decodeAttenuation(d)); + if (attenuation !== void 0) { + if (d.closeCompound()) { + return yourRef(oid, attenuation); + } + } + } + break; + } + default: + break; + } + } + d.restoreMark(M); + return void 0; +} diff --git a/src/relay.ts b/src/relay.ts index d177fef..c2ba01f 100644 --- a/src/relay.ts +++ b/src/relay.ts @@ -1,7 +1,7 @@ import { Actor, Assertion, Entity, Handle, Ref, Turn } from './actor.js'; -import { BytesLike, canonicalString, Decoder, encode, FlexMap, IdentityMap, mapPointers, underlying, Value } from '@preserves/core'; +import { Bytes, BytesLike, canonicalString, Decoder, encode, FlexMap, IdentityMap, mapPointers, underlying, Value } from '@preserves/core'; import * as IO from './gen/protocol.js'; -import { myRef, WireRef, WireSymbol, yourRef } from './protocol.js'; +import { decodeWireRef, myRef, WireRef, WireSymbol, yourRef } from './protocol.js'; import { queueTask } from './task.js'; import { attenuate } from './rewrite.js'; import { asAttenuation, Attenuation } from './gen/sturdy.js'; @@ -134,28 +134,8 @@ export class Relay { debug: boolean; trustPeer: boolean; - readonly decoder = new Decoder(void 0, { - includeAnnotations: false, - decodePointer: v => { - function complain(): never { - throw new Error( - `Received invalid object reference ${v.asPreservesText()} from peer`); - } - if (!(Array.isArray(v) && v.length >= 2 && typeof v[1] === 'number')) { - complain(); - } - const oid = v[1] as IO.Oid; - switch (v[0]) { - case 0: - if (v.length > 2) complain(); - return myRef(oid); - case 1: - return yourRef(oid, asAttenuation(v.slice(2))); - default: - complain(); - } - }, - }); + readonly decoder = new Decoder(void 0, { includeAnnotations: false }) + .replacePointerDecoder(decodeWireRef); constructor(t: Turn, options: RelayOptions) { this.actor = t.actor; @@ -249,11 +229,11 @@ export class Relay { if (this.debug) console.log('OUT', this.pendingTurn.asPreservesText()); this.w(underlying(encode(this.pendingTurn, { canonical: true, - encodePointer: n => { + encodePointer: (e, n) => { switch (n.loc) { - case 'mine': return [0, n.oid]; - case 'your': return [1, n.oid, ... mapPointers( - n.attenuation, pointerNotAllowed) as Array]; + case 'mine': return e.push([0, n.oid]); + case 'your': return e.push([1, n.oid, ... mapPointers( + n.attenuation, pointerNotAllowed) as Array]); } }, }))); @@ -271,9 +251,11 @@ export class Relay { Turn.for(this.actor, t => { this.decoder.write(bs); while (true) { - const wireTurn = this.decoder.try_next() as (IO.Turn | undefined); + const wireTurn = this.decoder.shortGuard( + () => IO.decodeTurn(this.decoder) ?? false, + () => void 0); if (wireTurn === void 0) break; - // TODO: deep check that wireTurn really is a TurnMessage + if (wireTurn === false) throw new Error("Bad IO.Turn"); if (this.debug) console.log('IN', wireTurn.asPreservesText()); wireTurn.forEach(v => { const [localOid, m] = v; diff --git a/yarn.lock b/yarn.lock index 911fb35..aaf6ea0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,17 +2,17 @@ # yarn lockfile v1 -"@preserves/core@^0.9.1": - version "0.9.1" - resolved "https://registry.yarnpkg.com/@preserves/core/-/core-0.9.1.tgz#28e6a4ef86a6ba862d5bc6c33b9e39b70f8bb8ce" - integrity sha512-vpevynSi8sWPFmNMWeonDjLssSvy37pALQeNA4WecCO49SVVA1Kjx9u8D9eKVyPa/CDqB4bNMQ+pSycsZIhMtw== +"@preserves/core@^0.10.0": + version "0.10.0" + resolved "https://registry.yarnpkg.com/@preserves/core/-/core-0.10.0.tgz#263d2cbe570f25e7b61d1fcfa73ccfe11773ad22" + integrity sha512-WeOe+MY+CdhECttKVoeBaTWFbI8rbKGBH5Ik5D5S7CeG5VUD+QsA1pm3sd+q41D2XwA5KQC8e5NQiKL7a8Yjow== -"@preserves/schema@^0.2.1": - version "0.2.1" - resolved "https://registry.yarnpkg.com/@preserves/schema/-/schema-0.2.1.tgz#bf593cf87faa28089abd106c596f8d1d3255c5b3" - integrity sha512-UKEYlN4tBfiC2NJjJvGWvpA5sTySkgxX+UGNfeNlLZ4V+93jo6aJ6f1eafLuuOEXNL0leaUzFAbWfZf2IbtXtQ== +"@preserves/schema@^0.3.1": + version "0.3.1" + resolved "https://registry.yarnpkg.com/@preserves/schema/-/schema-0.3.1.tgz#6db441771d7653a9b0f0bd575726838422ab8521" + integrity sha512-HjGkqJjYu0sfIH1dStG+dixetgZaSnlHnGUrPCkQvSaUlzJbBR4YRbM3mx2z6pFNDdYCuboA6nWgKaNsbj+KmQ== dependencies: - "@preserves/core" "^0.9.1" + "@preserves/core" "^0.10.0" "@types/glob" "^7.1.3" "@types/minimatch" "^3.0.3" "@types/yargs" "^16.0.0"