use std::rc::Rc;
use sim_kernel::{Cx, Expr, Result};
use sim_lib_view::{SurfaceCaps, SurfaceCodec};
use crate::{DeviceProfile, EncodedScene, LocalAdapter};
#[derive(Clone, Debug)]
pub struct Split<A> {
adapter: A,
profile: DeviceProfile,
}
impl<A> Split<A> {
pub fn new(adapter: A, profile: DeviceProfile) -> Self {
Self { adapter, profile }
}
pub fn adapter(&self) -> &A {
&self.adapter
}
pub fn profile(&self) -> &DeviceProfile {
&self.profile
}
}
impl<A: LocalAdapter> Split<A> {
pub fn encode_once<C: SurfaceCodec + ?Sized>(
&self,
codec: &C,
cx: &mut Cx,
value: &Expr,
caps: &SurfaceCaps,
) -> Result<EncodedScene> {
codec.encode(cx, value, caps).map(EncodedScene::new)
}
pub fn adapt_one(&self, encoded: &EncodedScene, state: &A::State) -> Result<Rc<Expr>> {
self.adapter.adapt(encoded, state, &self.profile)
}
pub fn adapt_many(&self, encoded: &EncodedScene, states: &[A::State]) -> Result<Vec<Rc<Expr>>> {
drive(encoded, &self.adapter, states, &self.profile)
}
pub fn run<C: SurfaceCodec + ?Sized>(
&self,
codec: &C,
cx: &mut Cx,
value: &Expr,
caps: &SurfaceCaps,
states: &[A::State],
) -> Result<SplitRun> {
let encoded = self.encode_once(codec, cx, value, caps)?;
let frames = self.adapt_many(&encoded, states)?;
Ok(SplitRun { encoded, frames })
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct SplitRun {
pub encoded: EncodedScene,
pub frames: Vec<Rc<Expr>>,
}
pub fn drive<A: LocalAdapter>(
encoded: &EncodedScene,
adapter: &A,
states: &[A::State],
profile: &DeviceProfile,
) -> Result<Vec<Rc<Expr>>> {
states
.iter()
.map(|state| adapter.adapt(encoded, state, profile))
.collect()
}