use std::{marker::PhantomData, sync::Arc};
use serde::{Deserialize, Serialize};
use super::Layer;
use crate::{
EffectFFI,
bridge::{BridgeError, EffectId, FfiFormat, ResolveRegistry},
};
#[doc(hidden)]
pub type EffectCallback<Format> =
dyn Fn(Result<Vec<u8>, BridgeError<Format>>) + Send + Sync + 'static;
pub struct Bridge<Next, Format>
where
Next: Layer,
Format: FfiFormat,
{
next: Next,
effect_callback: Arc<EffectCallback<Format>>,
registry: Arc<ResolveRegistry<Format>>,
format: PhantomData<Format>,
}
impl<Next, Format> Bridge<Next, Format>
where
Next: Layer,
Next::Event: for<'a> Deserialize<'a>,
Next::Effect: EffectFFI,
Format: FfiFormat,
{
pub fn new<F>(next: Next, effect_callback: F) -> Self
where
F: Fn(Result<Vec<u8>, BridgeError<Format>>) + Send + Sync + 'static,
{
Self {
next,
effect_callback: Arc::new(effect_callback),
registry: Arc::new(ResolveRegistry::default()),
format: PhantomData,
}
}
pub fn update(
&self,
event_bytes: &[u8],
requests_out: &mut Vec<u8>,
) -> Result<(), BridgeError<Format>> {
self.process(None, event_bytes, requests_out)
}
pub fn resolve(
&self,
id: EffectId,
output: &[u8],
requests_out: &mut Vec<u8>,
) -> Result<(), BridgeError<Format>> {
self.process(Some(id), output, requests_out)
}
fn process(
&self,
id: Option<EffectId>,
event_or_output: &[u8],
requests_out: &mut Vec<u8>,
) -> Result<(), BridgeError<Format>> {
let effect_callback = {
let shell_callback = self.effect_callback.clone();
let registry = self.registry.clone();
move |effects: Vec<Next::Effect>| {
let requests: Vec<_> = effects
.into_iter()
.map(|eff| registry.register(eff))
.collect();
let mut requests_bytes = vec![];
let result = {
Format::serialize(&mut requests_bytes, &requests)
.map_err(BridgeError::SerializeRequests)
};
shell_callback(result.map(|()| requests_bytes));
}
};
let effects = match id {
None => {
let shell_event =
Format::deserialize(event_or_output).map_err(BridgeError::DeserializeEvent)?;
self.next.update(shell_event, effect_callback)
}
Some(id) => {
self.registry.resume(id, event_or_output)?;
self.next.process_tasks(effect_callback)
}
};
let requests: Vec<_> = effects
.into_iter()
.map(|eff| self.registry.register(eff))
.collect();
Format::serialize(requests_out, &requests).map_err(BridgeError::SerializeRequests)?;
Ok(())
}
pub fn view(&self, view_out: &mut Vec<u8>) -> Result<(), BridgeError<Format>>
where
Next::ViewModel: Serialize,
{
Format::serialize(view_out, &self.next.view()).map_err(BridgeError::SerializeView)
}
}