Skip to main content

sim_run_core/
device_options.rs

1//! Reusable route option models for device product verbs.
2
3use std::fmt;
4
5use sim_kernel::Symbol;
6
7use crate::device_host::RouteArg;
8
9const GLASSES_ROUTE_OPTIONS: &[&str] = &[
10    "direct-linux",
11    "android-usb",
12    "neckband-local",
13    "neckband-relay",
14    "mobile-dock-display",
15    "ble-direct",
16    "web-bluetooth",
17    "phone-relay",
18    "controller-hid",
19];
20
21/// Closed command-line option set that resolves to open route symbols.
22#[derive(Clone, Copy, Debug, PartialEq, Eq)]
23pub struct DeviceRouteOptionModel {
24    options: &'static [&'static str],
25}
26
27impl DeviceRouteOptionModel {
28    /// Returns the glasses route option model.
29    pub const fn glasses() -> Self {
30        Self {
31            options: GLASSES_ROUTE_OPTIONS,
32        }
33    }
34
35    /// Returns the accepted option tokens in display order.
36    pub const fn options(self) -> &'static [&'static str] {
37        self.options
38    }
39
40    /// Parses one option into the route argument consumed by device composition.
41    pub fn parse(self, value: &str) -> Result<RouteArg, DeviceRouteOptionError> {
42        if self.options.contains(&value) {
43            Ok(RouteArg::new(Symbol::qualified("device/route", value)))
44        } else {
45            Err(DeviceRouteOptionError {
46                value: value.to_owned(),
47                expected: self.options,
48            })
49        }
50    }
51}
52
53/// Error returned when a device route option is not in the selected model.
54#[derive(Clone, Debug, PartialEq, Eq)]
55pub struct DeviceRouteOptionError {
56    value: String,
57    expected: &'static [&'static str],
58}
59
60impl DeviceRouteOptionError {
61    /// Returns the rejected option token.
62    pub fn value(&self) -> &str {
63        &self.value
64    }
65
66    /// Returns the accepted option tokens.
67    pub const fn expected(&self) -> &'static [&'static str] {
68        self.expected
69    }
70}
71
72impl fmt::Display for DeviceRouteOptionError {
73    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
74        write!(
75            f,
76            "unsupported device route '{}'; expected one of: {}",
77            self.value,
78            self.expected.join(", ")
79        )
80    }
81}
82
83impl std::error::Error for DeviceRouteOptionError {}
84
85#[cfg(test)]
86#[path = "device_options_tests.rs"]
87mod tests;