sim_lib_view_device/adapter.rs
1//! Device-local adapters for already encoded Scenes.
2
3use std::rc::Rc;
4
5use sim_kernel::{Expr, Result};
6
7use crate::DeviceProfile;
8
9/// A content-rate Scene shared across device-rate local adaptations.
10///
11/// The shared pointer is part of the contract: a display-only mirror path can
12/// reuse the exact encoded tree for every device frame without deep-cloning the
13/// Scene.
14#[derive(Clone, Debug, PartialEq)]
15pub struct EncodedScene {
16 scene: Rc<Expr>,
17}
18
19impl EncodedScene {
20 /// Wraps an owned encoded Scene in shared storage.
21 pub fn new(scene: Expr) -> Self {
22 Self {
23 scene: Rc::new(scene),
24 }
25 }
26
27 /// Wraps an already shared encoded Scene.
28 pub fn from_shared(scene: Rc<Expr>) -> Self {
29 Self { scene }
30 }
31
32 /// Borrows the encoded Scene expression.
33 pub fn expr(&self) -> &Expr {
34 &self.scene
35 }
36
37 /// Clones the shared pointer to the encoded Scene.
38 pub fn shared(&self) -> Rc<Expr> {
39 Rc::clone(&self.scene)
40 }
41}
42
43/// The latency-critical, device-local last step of surface projection.
44///
45/// A local adapter is pure: it receives an already encoded Scene, the freshest
46/// device-local state, and the typed device profile. It does not receive a
47/// runtime context, cannot call SIM code, and cannot re-enter the content
48/// encoder.
49pub trait LocalAdapter {
50 /// Device-local state consumed by the adapter.
51 type State;
52
53 /// Adapts an already encoded Scene for one device state sample.
54 fn adapt(
55 &self,
56 scene: &EncodedScene,
57 state: &Self::State,
58 profile: &DeviceProfile,
59 ) -> Result<Rc<Expr>>;
60}
61
62/// Display-only adapter that mirrors the encoded Scene unchanged.
63///
64/// This is the degenerate device case: the same shared Scene pointer is returned
65/// for every frame, so the tree is not cloned per adaptation.
66#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
67pub struct MirrorAdapter;
68
69impl LocalAdapter for MirrorAdapter {
70 type State = ();
71
72 fn adapt(
73 &self,
74 scene: &EncodedScene,
75 _state: &Self::State,
76 _profile: &DeviceProfile,
77 ) -> Result<Rc<Expr>> {
78 Ok(scene.shared())
79 }
80}