crux_core/bridge/request_serde.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
use crate::{
capability::Operation,
core::{Resolve, ResolveError},
Request,
};
// used in docs/internals/bridge.md
// ANCHOR: resolve_serialized
type ResolveOnceSerialized = Box<dyn FnOnce(&mut dyn erased_serde::Deserializer) + Send>;
type ResolveManySerialized =
Box<dyn FnMut(&mut dyn erased_serde::Deserializer) -> Result<(), ()> + Send>;
/// A deserializing version of Resolve
///
/// ResolveSerialized is a separate type because lifetime elision doesn't work
/// through generic type arguments. We can't create a ResolveRegistry of
/// Resolve<&[u8]> without specifying an explicit lifetime.
/// If you see a better way around this, please open a PR.
pub enum ResolveSerialized {
Never,
Once(ResolveOnceSerialized),
Many(ResolveManySerialized),
}
// ANCHOR_END: resolve_serialized
impl ResolveSerialized {
pub(crate) fn resolve(
&mut self,
bytes: &mut dyn erased_serde::Deserializer,
) -> Result<(), ResolveError> {
match self {
ResolveSerialized::Never => Err(ResolveError::Never),
ResolveSerialized::Many(f) => f(bytes).map_err(|_| ResolveError::FinishedMany),
ResolveSerialized::Once(_) => {
// The resolve has been used, turn it into a Never
if let ResolveSerialized::Once(f) =
std::mem::replace(self, ResolveSerialized::Never)
{
f(bytes);
}
Ok(())
}
}
}
}
impl<Op> Request<Op>
where
Op: Operation,
{
/// Serialize this effect request using `effect` as a constructor
/// for a serializable Effect `Eff`
///
/// You should never need to call this method yourself, it will be called
/// by the generated implementation of [`Effect::serialize`](crate::Effect::serialize),
/// which is used by the Bridge implementation.
pub fn serialize<F, Eff>(self, effect: F) -> (Eff, ResolveSerialized)
where
F: FnOnce(Op) -> Eff,
{
// FIXME should Eff be bound as `Serializable`?
let (operation, resolve) = (self.operation, self.resolve);
let resolve = resolve.deserializing(move |deserializer| {
erased_serde::deserialize(deserializer).expect("Deserialization failed")
});
(effect(operation), resolve)
}
}
impl<Out> Resolve<Out> {
/// Convert this Resolve into a version which deserializes from bytes, consuming it.
/// The `func` argument is a 'deserializer' converting from bytes into the `Out` type.
fn deserializing<F>(self, mut func: F) -> ResolveSerialized
where
F: (FnMut(&mut dyn erased_serde::Deserializer) -> Out) + Send + Sync + 'static,
Out: 'static,
{
match self {
Resolve::Never => ResolveSerialized::Never,
Resolve::Once(resolve) => ResolveSerialized::Once(Box::new(move |deser| {
let out = func(deser);
resolve(out)
})),
Resolve::Many(resolve) => ResolveSerialized::Many(Box::new(move |deser| {
let out = func(deser);
resolve(out)
})),
}
}
}