use crate::{
Request,
capability::Operation,
core::{RequestHandle, ResolveError},
};
use super::{BridgeError, FfiFormat};
type ResolveOnceSerialized<T> = Box<dyn FnOnce(&[u8]) -> Result<(), BridgeError<T>> + Send>;
type ResolveManySerialized<T> = Box<dyn FnMut(&[u8]) -> Result<(), BridgeError<T>> + Send>;
pub enum ResolveSerialized<T: FfiFormat> {
Never,
Once(ResolveOnceSerialized<T>),
Many(ResolveManySerialized<T>),
}
impl<T: FfiFormat> ResolveSerialized<T> {
pub(crate) fn resolve(&mut self, response: &[u8]) -> Result<(), BridgeError<T>> {
match self {
ResolveSerialized::Never => Err(BridgeError::ProcessResponse(ResolveError::Never)),
ResolveSerialized::Many(f) => f(response),
ResolveSerialized::Once(_) => {
let ResolveSerialized::Once(f) = std::mem::replace(self, ResolveSerialized::Never)
else {
unreachable!("already resolved");
};
f(response)
}
}
}
}
impl<Op> Request<Op>
where
Op: Operation,
Op::Output: for<'de> serde::de::Deserialize<'de>,
{
pub fn serialize<F, Eff, T>(self, effect: F) -> (Eff, ResolveSerialized<T>)
where
F: FnOnce(Op) -> Eff,
T: FfiFormat,
{
let handle = self.handle.deserializing(move |response| {
T::deserialize(response).map_err(BridgeError::DeserializeOutput)
});
(effect(self.operation), handle)
}
}
impl<Out> RequestHandle<Out> {
fn deserializing<F, T>(self, mut func: F) -> ResolveSerialized<T>
where
F: (FnMut(&[u8]) -> Result<Out, BridgeError<T>>) + Send + Sync + 'static,
T: FfiFormat,
Out: 'static,
{
match self {
RequestHandle::Never => ResolveSerialized::Never,
RequestHandle::Once(resolve) => ResolveSerialized::Once(Box::new(move |response| {
let out = func(response)?;
resolve(out);
Ok(())
})),
RequestHandle::Many(resolve) => ResolveSerialized::Many(Box::new(move |response| {
let out = func(response)?;
resolve(out).map_err(|()| BridgeError::ProcessResponse(ResolveError::FinishedMany))
})),
}
}
}