Repair reimported, attenuated references.

This commit is contained in:
Tony Garnock-Jones 2024-03-22 20:51:02 +01:00
parent 40a239c9eb
commit 0b72b4029b
1 changed files with 38 additions and 20 deletions

View File

@ -29,6 +29,7 @@ use preserves::value::Map;
use preserves::value::NestedValue; use preserves::value::NestedValue;
use preserves::value::NoEmbeddedDomainCodec; use preserves::value::NoEmbeddedDomainCodec;
use preserves::value::PackedWriter; use preserves::value::PackedWriter;
use preserves::value::Set;
use preserves::value::TextWriter; use preserves::value::TextWriter;
use preserves::value::ViaCodec; use preserves::value::ViaCodec;
use preserves::value::Writer; use preserves::value::Writer;
@ -76,6 +77,7 @@ struct Membranes {
exported: Membrane, exported: Membrane,
imported: Membrane, imported: Membrane,
next_export_oid: usize, next_export_oid: usize,
reimported_attenuations: Map<sturdy::Oid, Set<Arc<Cap>>>,
} }
pub enum Input { pub enum Input {
@ -172,6 +174,11 @@ impl Membrane {
ws ws
} }
fn remove(&mut self, ws: &Arc<WireSymbol>) {
self.oid_map.remove(&ws.oid);
self.ref_map.remove(&ws.obj);
}
fn insert_inert_entity(&mut self, t: &mut Activation, oid: sturdy::Oid) -> Arc<WireSymbol> { fn insert_inert_entity(&mut self, t: &mut Activation, oid: sturdy::Oid) -> Arc<WireSymbol> {
self.insert(oid, Cap::new(&t.inert_entity())) self.insert(oid, Cap::new(&t.inert_entity()))
} }
@ -259,6 +266,7 @@ impl TunnelRelay {
exported: Membrane::new(WireSymbolSide::Exported), exported: Membrane::new(WireSymbolSide::Exported),
imported: Membrane::new(WireSymbolSide::Imported), imported: Membrane::new(WireSymbolSide::Imported),
next_export_oid: 0, next_export_oid: 0,
reimported_attenuations: Map::new(),
}, },
pending_outbound: Vec::new(), pending_outbound: Vec::new(),
}; };
@ -550,9 +558,10 @@ impl Membranes {
#[inline] #[inline]
fn release_one(&mut self, ws: Arc<WireSymbol>) -> bool { fn release_one(&mut self, ws: Arc<WireSymbol>) -> bool {
if ws.dec_ref() { if ws.dec_ref() {
let membrane = self.membrane(ws.side); if let WireSymbolSide::Exported = ws.side {
membrane.oid_map.remove(&ws.oid); self.reimported_attenuations.remove(&ws.oid);
membrane.ref_map.remove(&ws.obj); }
self.membrane(ws.side).remove(&ws);
true true
} else { } else {
false false
@ -573,34 +582,43 @@ impl Membranes {
src: &'src mut S, src: &'src mut S,
_read_annotations: bool, _read_annotations: bool,
) -> io::Result<Arc<Cap>> { ) -> io::Result<Arc<Cap>> {
let ws = match sturdy::WireRef::deserialize(&mut src.packed(NoEmbeddedDomainCodec))? { match sturdy::WireRef::deserialize(&mut src.packed(NoEmbeddedDomainCodec))? {
sturdy::WireRef::Mine{ oid: b } => { sturdy::WireRef::Mine{ oid: b } => {
let oid = *b; let oid = *b;
self.imported.oid_map.get(&oid).map(Arc::clone) let ws = self.imported.oid_map.get(&oid).map(Arc::clone)
.unwrap_or_else(|| self.import_oid(t, relay_ref, oid)) .unwrap_or_else(|| self.import_oid(t, relay_ref, oid));
Ok(Arc::clone(&ws.inc_ref().obj))
} }
sturdy::WireRef::Yours { oid: b, attenuation } => { sturdy::WireRef::Yours { oid: b, attenuation } => {
let oid = *b; let oid = *b;
let ws = self.exported.oid_map.get(&oid).map(Arc::clone)
.unwrap_or_else(|| self.exported.insert_inert_entity(t, oid.clone()));
if attenuation.is_empty() { if attenuation.is_empty() {
self.exported.oid_map.get(&oid).map(Arc::clone).unwrap_or_else( Ok(Arc::clone(&ws.inc_ref().obj))
|| self.exported.insert_inert_entity(t, oid))
} else { } else {
match self.exported.oid_map.get(&oid) { let attenuated_obj = ws.obj.attenuate(&attenuation)
None => self.exported.insert_inert_entity(t, oid), .map_err(|e| {
Some(ws) => { io::Error::new(
let attenuated_obj = ws.obj.attenuate(&attenuation) io::ErrorKind::InvalidInput,
.map_err(|e| { format!("Invalid capability attenuation: {:?}", e))
io::Error::new( })?;
io::ErrorKind::InvalidInput,
format!("Invalid capability attenuation: {:?}", e)) ws.inc_ref();
})?;
self.exported.insert(oid, attenuated_obj) let variations = self.reimported_attenuations.entry(oid).or_default();
match variations.get(&attenuated_obj) {
None => {
variations.insert(Arc::clone(&attenuated_obj));
self.exported.ref_map.insert(Arc::clone(&attenuated_obj), Arc::clone(&ws));
Ok(attenuated_obj)
} }
Some(existing) =>
Ok(Arc::clone(existing))
} }
} }
} }
}; }
Ok(Arc::clone(&ws.inc_ref().obj))
} }
} }