mod formats;
mod registry;
mod request_serde;
use facet::Facet;
use serde::{Deserialize, Serialize};
use std::fmt::Debug;
use thiserror::Error;
use crate::{App, Core, core::ResolveError};
pub use formats::{BincodeFfiFormat, JsonFfiFormat};
pub use registry::EffectId;
pub(crate) use registry::ResolveRegistry;
#[doc(hidden)]
pub use request_serde::ResolveSerialized;
pub trait FfiFormat: Debug + 'static {
type Error: std::error::Error;
fn serialize<T: Serialize>(buffer: &mut Vec<u8>, value: &T) -> Result<(), Self::Error>;
fn deserialize<'de, T: Deserialize<'de>>(bytes: &'de [u8]) -> Result<T, Self::Error>;
}
#[derive(Facet, Debug, Serialize, Deserialize)]
pub struct Request<Eff>
where
Eff: Serialize,
{
pub id: EffectId,
pub effect: Eff,
}
#[derive(Facet, Debug, Serialize, Deserialize)]
#[serde(transparent)]
pub struct Requests<Eff>(pub Vec<Request<Eff>>)
where
Eff: Serialize;
pub struct Bridge<A, F = BincodeFfiFormat>
where
A: App,
F: FfiFormat,
{
core: Core<A>,
registry: ResolveRegistry<F>,
}
#[derive(Debug, Error)]
pub enum BridgeError<F: FfiFormat = BincodeFfiFormat> {
#[error("could not deserialize event: {0}")]
DeserializeEvent(F::Error),
#[error("could not deserialize provided effect output: {0}")]
DeserializeOutput(F::Error),
#[error("could not process response: {0}")]
ProcessResponse(#[from] ResolveError),
#[error("could not serialize effect requests: {0}")]
SerializeRequests(F::Error),
#[error("could not serialize view model: {0}")]
SerializeView(F::Error),
}
impl<A, Format> Bridge<A, Format>
where
A: App,
Format: FfiFormat,
{
pub fn new(core: Core<A>) -> Self {
Self {
core,
registry: ResolveRegistry::default(),
}
}
#[deprecated(
since = "0.17.0",
note = "Bridge API returning vectors has been deprecated. Please use the 'update' method."
)]
pub fn process_event(&self, event: &[u8]) -> Result<Vec<u8>, BridgeError<Format>>
where
A::Event: for<'a> Deserialize<'a>,
A::Effect: crate::core::EffectFFI,
{
let mut return_buffer = vec![];
self.update(event, &mut return_buffer)?;
Ok(return_buffer)
}
pub fn update<'a>(
&self,
event: &'a [u8],
requests_out: &mut Vec<u8>,
) -> Result<(), BridgeError<Format>>
where
A::Event: Deserialize<'a>,
A::Effect: crate::core::EffectFFI,
{
self.process(None, event, requests_out)
}
#[deprecated(
since = "0.17.0",
note = "Bridge API returning vectors has been deprecated. Please use the 'resolve' method."
)]
pub fn handle_response(&self, id: u32, output: &[u8]) -> Result<Vec<u8>, BridgeError<Format>>
where
A::Event: for<'a> Deserialize<'a>,
A::Effect: crate::core::EffectFFI,
{
let mut return_buffer = vec![];
self.resolve(EffectId(id), output, &mut return_buffer)?;
Ok(return_buffer)
}
pub fn resolve<'a>(
&self,
id: EffectId,
response: &'a [u8],
requests_out: &mut Vec<u8>,
) -> Result<(), BridgeError<Format>>
where
A::Event: Deserialize<'a>,
A::Effect: crate::core::EffectFFI,
{
self.process(Some(id), response, requests_out)
}
fn process<'a>(
&self,
id: Option<EffectId>,
data: &'a [u8],
requests_out: &mut Vec<u8>,
) -> Result<(), BridgeError<Format>>
where
A::Event: Deserialize<'a>,
A::Effect: crate::core::EffectFFI,
{
let effects = match id {
None => {
let shell_event =
Format::deserialize(data).map_err(BridgeError::DeserializeEvent)?;
self.core.process_event(shell_event)
}
Some(id) => {
self.registry.resume(id, data)?;
self.core.process()
}
};
self.process_effects(effects, requests_out)
}
fn process_effects(
&self,
effects: Vec<A::Effect>,
requests_out: &mut Vec<u8>,
) -> Result<(), BridgeError<Format>>
where
A::Effect: crate::core::EffectFFI,
{
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
A::ViewModel: Serialize,
{
Format::serialize(view_out, &self.core.view()).map_err(BridgeError::SerializeView)
}
}