Replace boundary structure to preserve embedded value separation

This commit is contained in:
Tony Garnock-Jones 2024-03-12 22:56:01 +01:00
parent 9521fc3dcc
commit 40f5ef4085
2 changed files with 27 additions and 26 deletions

View File

@ -2,22 +2,22 @@
/// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
import * as S from '../gen/sturdy.js';
import { Decoder, DecoderState, Encoder, EncoderState, GenericEmbedded, neverEmbeddedType, EmbeddedType, Value, EmbeddedWriter } from '@preserves/core';
import { Decoder, DecoderState, Encoder, EncoderState, GenericEmbedded, neverEmbeddedType, EmbeddedType, Value, Embedded, EmbeddedWriter } from '@preserves/core';
export const wireRefEmbeddedType: EmbeddedType<S.WireRef> & EmbeddedWriter<S.WireRef> = {
decode(s: DecoderState): S.WireRef {
return S.asWireRef(new Decoder<any>(s).next());
export const wireRefEmbeddedType: EmbeddedType<Embedded<S.WireRef>> & EmbeddedWriter<Embedded<S.WireRef>> = {
decode(s: DecoderState): Embedded<S.WireRef> {
return new Embedded<S.WireRef>(S.asWireRef(new Decoder<any>(s).next()));
},
encode(s: EncoderState, v: S.WireRef): void {
new Encoder<any>(s, neverEmbeddedType).push(S.fromWireRef(v));
encode(s: EncoderState, v: Embedded<S.WireRef>): void {
new Encoder<any>(s, neverEmbeddedType).push(S.fromWireRef(v.value));
},
fromValue(v: Value<GenericEmbedded>): S.WireRef {
return S.asWireRef(v as Value<S._embedded>);
fromValue(v: Value<GenericEmbedded>): Embedded<S.WireRef> {
return new Embedded<S.WireRef>(S.asWireRef(v as Value<S._embedded>));
},
toValue(v: S.WireRef): Value<GenericEmbedded> {
return S.fromWireRef(v) as Value<GenericEmbedded>;
toValue(v: Embedded<S.WireRef>): Value<GenericEmbedded> {
return S.fromWireRef(v.value) as Value<GenericEmbedded>;
}
};

View File

@ -2,7 +2,7 @@
/// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
import { Actor, Assertion, Entity, Facet, Handle, Ref, Turn } from '../runtime/actor.js';
import { BytesLike, Decoder, Dictionary, encode, IdentityMap, mapEmbeddeds, stringify, underlying, Value } from '@preserves/core';
import { BytesLike, Decoder, Dictionary, encode, IdentityMap, mapEmbeddeds, Embedded, stringify, underlying, Value } from '@preserves/core';
import * as IO from '../gen/protocol.js';
import { wireRefEmbeddedType } from './protocol.js';
import { attenuate } from '../runtime/rewrite.js';
@ -68,7 +68,7 @@ export class RelayEntity implements Entity {
this.oid = oid;
}
send(m: IO.Event<WireRef>): void {
send(m: IO.Event<Embedded<WireRef>>): void {
this.relay.send(this.oid, m);
}
@ -156,7 +156,7 @@ export class Relay {
readonly imported = new Membrane();
readonly peer: Ref | null;
nextLocalOid: IO.Oid = 0;
pendingTurn: IO.Turn<WireRef> = [];
pendingTurn: IO.Turn<Embedded<WireRef>> = [];
debug: boolean;
trustPeer: boolean;
@ -180,7 +180,7 @@ export class Relay {
}
this.peer = (options.initialOid !== void 0)
? this.rewriteRefIn(WireRef.mine(options.initialOid), [])
? this.rewriteRefIn(new Embedded<WireRef>(WireRef.mine(options.initialOid)), [])
: null;
if (options.nextLocalOid !== void 0) {
@ -188,9 +188,9 @@ export class Relay {
}
}
register(targetRemoteOid: IO.Oid, assertion: Assertion, handle: Handle): Value<WireRef>;
register(targetRemoteOid: null, assertion: Assertion, handle: null): Value<WireRef>;
register(targetRemoteOid: IO.Oid | null, assertion: Assertion, handle: Handle | null): Value<WireRef> {
register(targetRemoteOid: IO.Oid, assertion: Assertion, handle: Handle): Value<Embedded<WireRef>>;
register(targetRemoteOid: null, assertion: Assertion, handle: null): Value<Embedded<WireRef>>;
register(targetRemoteOid: IO.Oid | null, assertion: Assertion, handle: Handle | null): Value<Embedded<WireRef>> {
const transient = (handle === null);
const pins: Array<WireSymbol> = [];
const rewritten = mapEmbeddeds(assertion, r => this.rewriteRefOut(r, transient, pins));
@ -223,18 +223,18 @@ export class Relay {
return e.ref;
}
rewriteRefOut(r: Ref, transient: boolean, pins: Array<WireSymbol>): WireRef {
rewriteRefOut(r: Ref, transient: boolean, pins: Array<WireSymbol>): Embedded<WireRef> {
if (r.target instanceof RelayEntity && r.target.relay === this) {
if (r.attenuation === void 0 || r.attenuation.length === 0) {
// No extra conditions on this reference since it was sent to us.
this.grabImportedOid(r.target.oid, pins);
return WireRef.yours({ oid: r.target.oid, attenuation: [] });
return new Embedded<WireRef>(WireRef.yours({ oid: r.target.oid, attenuation: [] }));
} else {
// This reference has been attenuated since it was sent to us.
// Do we trust the peer to enforce such attenuation on our behalf?
if (this.trustPeer) {
this.grabImportedOid(r.target.oid, pins);
return WireRef.yours({ oid: r.target.oid, attenuation: r.attenuation });
return new Embedded<WireRef>(WireRef.yours({ oid: r.target.oid, attenuation: r.attenuation }));
} else {
// fall through: treat the attenuated ref as a local ref, and re-export it.
}
@ -247,10 +247,11 @@ export class Relay {
return new WireSymbol(this.exported, this.nextLocalOid++, r);
});
pins.push(e);
return WireRef.mine(e.oid);
return new Embedded<WireRef>(WireRef.mine(e.oid));
}
rewriteRefIn(n: WireRef, pins: Array<WireSymbol>): Ref {
rewriteRefIn(nw: Embedded<WireRef>, pins: Array<WireSymbol>): Ref {
const n = nw.value;
switch (n._variant) {
case 'yours': {
const e = this.exported.grab("byOid", n.oid, false, null);
@ -283,7 +284,7 @@ export class Relay {
message(body: Assertion) {
if (body === FLUSH) {
if (this.debug) console.log('OUT', stringify(IO.fromTurn(this.pendingTurn)));
if (this.debug) console.log('OUT', stringify(IO.fromTurn(this.pendingTurn)), this.pendingTurn);
this.w(underlying(encode(IO.fromTurn(this.pendingTurn), {
canonical: true,
embeddedEncode: wireRefEmbeddedType,
@ -292,7 +293,7 @@ export class Relay {
}
}
send(remoteOid: IO.Oid, m: IO.Event<WireRef>): void {
send(remoteOid: IO.Oid, m: IO.Event<Embedded<WireRef>>): void {
if (this.pendingTurn.length === 0) {
Turn.active.message(this.selfRef, FLUSH);
}
@ -313,14 +314,14 @@ export class Relay {
});
}
rewriteIn(a: Value<WireRef>): [Assertion, Array<WireSymbol>]
rewriteIn(a: Value<Embedded<WireRef>>): [Assertion, Array<WireSymbol>]
{
const pins: Array<WireSymbol> = [];
const rewritten = mapEmbeddeds(a, r => this.rewriteRefIn(r, pins));
return [rewritten, pins];
}
handle(localOid: IO.Oid, m: IO.Event<WireRef>) {
handle(localOid: IO.Oid, m: IO.Event<Embedded<WireRef>>) {
switch (m._variant) {
case 'Assert': {
const [a, pins] = this.rewriteIn(m.value.assertion);