sim_lib_stream_host/
device.rs1use std::fmt;
4
5use sim_kernel::{Expr, Symbol};
6
7pub type DeviceResult<T> = std::result::Result<T, DeviceError>;
9
10#[derive(Clone, Debug, PartialEq, Eq)]
12pub enum DeviceError {
13 Unsupported,
15 Sample(String),
17 Host(String),
19}
20
21impl fmt::Display for DeviceError {
22 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
23 match self {
24 Self::Unsupported => f.write_str("device provider is unsupported"),
25 Self::Sample(message) => write!(f, "device sample error: {message}"),
26 Self::Host(message) => f.write_str(message),
27 }
28 }
29}
30
31impl std::error::Error for DeviceError {}
32
33impl From<DeviceError> for sim_kernel::Error {
34 fn from(error: DeviceError) -> Self {
35 match error {
36 DeviceError::Unsupported => {
37 Self::HostError("device provider is unsupported".to_owned())
38 }
39 DeviceError::Sample(message) => Self::Eval(format!("device sample error: {message}")),
40 DeviceError::Host(message) => Self::HostError(message),
41 }
42 }
43}
44
45#[derive(Clone, Debug, PartialEq, Eq)]
47pub struct DeviceProfile {
48 pub device: Symbol,
50 pub streams: Vec<Symbol>,
52 pub inputs: Vec<Symbol>,
54 pub outputs: Vec<Symbol>,
56 pub sample_kinds: Vec<Symbol>,
58}
59
60impl DeviceProfile {
61 pub fn new(
63 device: Symbol,
64 streams: Vec<Symbol>,
65 inputs: Vec<Symbol>,
66 outputs: Vec<Symbol>,
67 sample_kinds: Vec<Symbol>,
68 ) -> Self {
69 Self {
70 device,
71 streams,
72 inputs,
73 outputs,
74 sample_kinds,
75 }
76 }
77
78 pub fn modeled_edge() -> Self {
80 Self::new(
81 Symbol::qualified("device", "modeled-edge"),
82 vec![
83 Symbol::qualified("device/stream", "battery"),
84 Symbol::qualified("device/stream", "motion"),
85 ],
86 vec![Symbol::qualified("device/input", "button")],
87 vec![
88 Symbol::qualified("device/output", "screen"),
89 Symbol::qualified("device/output", "haptic"),
90 ],
91 vec![device_sample_kind_symbol("device-caps")],
92 )
93 }
94
95 pub fn supports_sample_kind(&self, sample_kind: &Symbol) -> bool {
97 self.sample_kinds.contains(sample_kind)
98 }
99}
100
101pub trait DeviceSample: Sized {
103 fn sample_kind() -> &'static str;
105
106 fn to_expr(&self) -> Expr;
108
109 fn from_expr(expr: &Expr) -> DeviceResult<Self>;
111}
112
113pub fn device_sample_kind_symbol(kind: &str) -> Symbol {
115 Symbol::qualified("stream/device-sample", kind)
116}
117
118pub trait DeviceProvider: Send {
120 fn open(&self) -> DeviceResult<Box<dyn DeviceSession>>;
122}
123
124pub trait DeviceSession: Send {
126 fn profile(&self) -> &DeviceProfile;
128
129 fn start(&mut self) -> DeviceResult<()>;
131
132 fn poll(&mut self, kind: &str) -> DeviceResult<Option<Expr>>;
134
135 fn send(&mut self, command: &Expr) -> DeviceResult<()>;
137
138 fn stop(&mut self) -> DeviceResult<()>;
140}
141
142pub fn poll_device_sample<S>(session: &mut dyn DeviceSession) -> DeviceResult<Option<S>>
144where
145 S: DeviceSample,
146{
147 session
148 .poll(S::sample_kind())?
149 .map(|expr| S::from_expr(&expr))
150 .transpose()
151}
152
153#[derive(Clone, Debug, PartialEq, Eq)]
155pub struct StubProvider {
156 profile: DeviceProfile,
157}
158
159impl StubProvider {
160 pub fn new(profile: DeviceProfile) -> Self {
162 Self { profile }
163 }
164
165 pub fn profile(&self) -> &DeviceProfile {
167 &self.profile
168 }
169
170 pub fn session(&self) -> StubSession {
172 StubSession::new(self.profile.clone())
173 }
174}
175
176impl DeviceProvider for StubProvider {
177 fn open(&self) -> DeviceResult<Box<dyn DeviceSession>> {
178 Err(DeviceError::Unsupported)
179 }
180}
181
182#[derive(Clone, Debug, PartialEq, Eq)]
184pub struct StubSession {
185 profile: DeviceProfile,
186}
187
188impl StubSession {
189 pub fn new(profile: DeviceProfile) -> Self {
191 Self { profile }
192 }
193}
194
195impl DeviceSession for StubSession {
196 fn profile(&self) -> &DeviceProfile {
197 &self.profile
198 }
199
200 fn start(&mut self) -> DeviceResult<()> {
201 Err(DeviceError::Unsupported)
202 }
203
204 fn poll(&mut self, _kind: &str) -> DeviceResult<Option<Expr>> {
205 Err(DeviceError::Unsupported)
206 }
207
208 fn send(&mut self, _command: &Expr) -> DeviceResult<()> {
209 Err(DeviceError::Unsupported)
210 }
211
212 fn stop(&mut self) -> DeviceResult<()> {
213 Ok(())
214 }
215}