crux_core/bridge/
registry.rs

1use std::sync::Mutex;
2
3use serde::{Deserialize, Serialize};
4use slab::Slab;
5
6use super::{BridgeError, Request};
7use crate::bridge::request_serde::ResolveSerialized;
8use crate::Effect;
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
11#[serde(transparent)]
12pub struct EffectId(pub u32);
13
14pub struct ResolveRegistry(Mutex<Slab<ResolveSerialized>>);
15
16impl Default for ResolveRegistry {
17    fn default() -> Self {
18        Self(Mutex::new(Slab::with_capacity(1024)))
19    }
20}
21
22impl ResolveRegistry {
23    /// Register an effect for future continuation, when it has been processed
24    /// and output given back to the core.
25    ///
26    /// The `effect` will be serialized into its FFI counterpart before being stored
27    /// and wrapped in a [`Request`].
28    // used in docs/internals/bridge.md
29    // ANCHOR: register
30    pub fn register<Eff>(&self, effect: Eff) -> Request<Eff::Ffi>
31    where
32        Eff: Effect,
33    {
34        let (effect, resolve) = effect.serialize();
35
36        let id = self
37            .0
38            .lock()
39            .expect("Registry Mutex poisoned.")
40            .insert(resolve);
41
42        Request {
43            id: EffectId(id.try_into().expect("EffectId overflow")),
44            effect,
45        }
46    }
47    // ANCHOR_END: register
48
49    /// Resume a previously registered effect. This may fail, either because EffectId wasn't
50    /// found or because this effect was not expected to be resumed again.
51    pub fn resume(
52        &self,
53        id: EffectId,
54        body: &mut dyn erased_serde::Deserializer,
55    ) -> Result<(), BridgeError> {
56        let mut registry_lock = self.0.lock().expect("Registry Mutex poisoned");
57
58        let entry = registry_lock.get_mut(id.0 as usize);
59
60        let Some(entry) = entry else {
61            // FIXME return an Err instead of panicking here.
62            panic!("Request with {id:?} not found.");
63        };
64
65        let resolved = entry.resolve(body);
66
67        if let ResolveSerialized::Never = entry {
68            registry_lock.remove(id.0 as usize);
69        }
70
71        resolved
72    }
73}