use std::rc::Rc;
use sim_kernel::{Error, Expr, Result};
use sim_value::build;
use crate::{
DeviceProfile, EncodedScene, GlanceBudget, GlanceInput, GlanceState, LocalAdapter,
fit_to_budget,
};
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct GlanceAdapter {
pub budget: GlanceBudget,
pub ack_ms: u64,
}
impl GlanceAdapter {
pub fn new(budget: GlanceBudget, ack_ms: u64) -> Self {
Self { budget, ack_ms }
}
}
impl LocalAdapter for GlanceAdapter {
type State = GlanceState;
fn adapt(
&self,
scene: &EncodedScene,
state: &Self::State,
_profile: &DeviceProfile,
) -> Result<Rc<Expr>> {
if !crate::glance::is_glance(scene.expr()) {
return Err(Error::HostError(
"GlanceAdapter expects an encoded scene/glance card".to_owned(),
));
}
let card = fit_to_budget(scene.expr(), &self.budget)?;
Ok(Rc::new(match state.pending_input {
Some(input) => with_ack(card, input, state.tick, self.budget, self.ack_ms),
None => card,
}))
}
}
fn with_ack(card: Expr, input: GlanceInput, tick: u64, budget: GlanceBudget, ack_ms: u64) -> Expr {
sim_value::access::set(
&sim_value::access::set(
&sim_value::access::set(
&sim_value::access::set(&card, "ack-channel", Expr::Symbol(budget.ack.to_symbol())),
"ack-input",
build::sym(input.token()),
),
"ack-ms",
build::uint(ack_ms),
),
"ack-tick",
build::uint(tick),
)
}