Skip to main content

roam_core/
lib.rs

1//! Core implementations for the roam connectivity layer.
2//!
3//! This crate provides concrete implementations of the traits defined in
4//! [`roam_types`]:
5//!
6//! - [`BareConduit`]: wraps a raw `Link` with postcard serialization.
7//!   No reconnect, no reliability. For localhost, SHM, testing.
8//! - `StableConduit` (TODO): wraps a Link + seq/ack/replay with
9//!   bytes-based replay buffer. Handles reconnect transparently.
10
11mod bare_conduit;
12pub use bare_conduit::*;
13
14mod into_conduit;
15pub use into_conduit::*;
16
17#[cfg(not(target_arch = "wasm32"))]
18mod stable_conduit;
19#[cfg(not(target_arch = "wasm32"))]
20pub use stable_conduit::*;
21
22#[cfg(not(target_arch = "wasm32"))]
23mod memory_link;
24#[cfg(not(target_arch = "wasm32"))]
25pub use memory_link::*;
26
27mod session;
28pub use session::*;
29
30#[cfg(not(target_arch = "wasm32"))]
31mod driver;
32#[cfg(not(target_arch = "wasm32"))]
33pub use driver::*;
34
35#[cfg(target_arch = "wasm32")]
36mod wasm_driver;
37#[cfg(target_arch = "wasm32")]
38pub use wasm_driver::*;
39
40use facet_format::{FormatDeserializer, MetaSource};
41use facet_postcard::PostcardParser;
42use facet_reflect::Partial;
43use roam_types::{Backing, SelfRef};
44
45/// Return a process-global cached `&'static RpcPlan` for type `T`.
46/// FIXME: requiring 'static here is wrong
47/// FIXME: this function is now useless since we have RpcPlan::for_type
48pub fn rpc_plan<T: facet::Facet<'static>>() -> &'static roam_types::RpcPlan {
49    roam_types::RpcPlan::for_type::<T>()
50}
51
52/// Deserialize postcard-encoded `backing` bytes into `T` in place, returning a
53/// [`roam_types::SelfRef`] that keeps the backing storage alive for the value.
54// r[impl zerocopy.framing.value]
55pub(crate) fn deserialize_postcard<T: facet::Facet<'static>>(
56    backing: Backing,
57) -> Result<SelfRef<T>, facet_format::DeserializeError> {
58    // SAFETY: backing is heap-allocated with a stable address.
59    // The SelfRef::try_new contract guarantees value is dropped before backing.
60    SelfRef::try_new(backing, |bytes| {
61        let mut value = std::mem::MaybeUninit::<T>::uninit();
62        let ptr = facet_core::PtrUninit::from_maybe_uninit(&mut value);
63
64        // SAFETY: ptr points to valid, aligned, properly-sized memory for T.
65        #[allow(unsafe_code)]
66        let partial: Partial<'_, true> = unsafe { Partial::from_raw_with_shape(ptr, T::SHAPE) }
67            .map_err(facet_format::DeserializeError::from)?;
68
69        let mut parser = PostcardParser::new(bytes);
70        let mut deserializer = FormatDeserializer::new(&mut parser);
71        let partial = deserializer.deserialize_into(partial, MetaSource::FromEvents)?;
72
73        partial
74            .finish_in_place()
75            .map_err(facet_format::DeserializeError::from)?;
76
77        // SAFETY: finish_in_place succeeded, so value is fully initialized.
78        #[allow(unsafe_code)]
79        Ok(unsafe { value.assume_init() })
80    })
81}
82
83#[cfg(test)]
84mod tests;