starnix_container_structured_config/
starnix_container_structured_config_rust_config_lib_source.rs

1use fidl::unpersist;
2use fidl_cf_sc_internal_starnixcontainerstructuredconfig::Config as FidlConfig;
3use fuchsia_inspect::{ArrayProperty, Node};
4use fuchsia_runtime::{take_startup_handle, HandleInfo, HandleType};
5use std::convert::TryInto;
6const EXPECTED_CHECKSUM: &[u8] = &[
7    0x4b, 0xf3, 0x71, 0xe5, 0x3b, 0xbc, 0x37, 0xbd, 0xb2, 0x65, 0xcf, 0x3b, 0xe3, 0xbe, 0x68, 0xd9,
8    0x9f, 0xfb, 0x03, 0x20, 0x1e, 0x53, 0x87, 0xd4, 0x2c, 0xa5, 0xe3, 0xe1, 0x29, 0x9e, 0xe6, 0x36,
9];
10#[derive(Debug)]
11pub struct Config {
12    pub enable_utc_time_adjustment: bool,
13    pub extra_features: Vec<String>,
14    pub mlock_always_onfault: bool,
15    pub mlock_pin_flavor: String,
16    pub ui_visual_debugging_level: u8,
17}
18impl Config {
19    #[doc = r" Take the config startup handle and parse its contents."]
20    #[doc = r""]
21    #[doc = r" # Panics"]
22    #[doc = r""]
23    #[doc = r" If the config startup handle was already taken or if it is not valid."]
24    pub fn take_from_startup_handle() -> Self {
25        let handle_info = HandleInfo::new(HandleType::ComponentConfigVmo, 0);
26        let config_vmo: zx::Vmo =
27            take_startup_handle(handle_info).expect("Config VMO handle must be present.").into();
28        Self::from_vmo(&config_vmo).expect("Config VMO handle must be valid.")
29    }
30    #[doc = r" Parse `Self` from `vmo`."]
31    pub fn from_vmo(vmo: &zx::Vmo) -> Result<Self, Error> {
32        let config_size = vmo.get_content_size().map_err(Error::GettingContentSize)?;
33        let config_bytes = vmo.read_to_vec(0, config_size).map_err(Error::ReadingConfigBytes)?;
34        Self::from_bytes(&config_bytes)
35    }
36    #[doc = r" Parse `Self` from `bytes`."]
37    pub fn from_bytes(bytes: &[u8]) -> Result<Self, Error> {
38        let (checksum_len_bytes, bytes) = bytes.split_at_checked(2).ok_or(Error::TooFewBytes)?;
39        let checksum_len_bytes: [u8; 2] =
40            checksum_len_bytes.try_into().expect("previous call guaranteed 2 element slice");
41        let checksum_length = u16::from_le_bytes(checksum_len_bytes) as usize;
42        let (observed_checksum, bytes) =
43            bytes.split_at_checked(checksum_length).ok_or(Error::TooFewBytes)?;
44        if observed_checksum != EXPECTED_CHECKSUM {
45            return Err(Error::ChecksumMismatch { observed_checksum: observed_checksum.to_vec() });
46        }
47        let fidl_config: FidlConfig = unpersist(bytes).map_err(Error::Unpersist)?;
48        Ok(Self {
49            enable_utc_time_adjustment: fidl_config.enable_utc_time_adjustment,
50            extra_features: fidl_config.extra_features,
51            mlock_always_onfault: fidl_config.mlock_always_onfault,
52            mlock_pin_flavor: fidl_config.mlock_pin_flavor,
53            ui_visual_debugging_level: fidl_config.ui_visual_debugging_level,
54        })
55    }
56    pub fn record_inspect(&self, inspector_node: &Node) {
57        inspector_node.record_bool("enable_utc_time_adjustment", self.enable_utc_time_adjustment);
58        let arr = inspector_node.create_string_array("extra_features", self.extra_features.len());
59        for i in 0..self.extra_features.len() {
60            arr.set(i, &self.extra_features[i]);
61        }
62        inspector_node.record(arr);
63        inspector_node.record_bool("mlock_always_onfault", self.mlock_always_onfault);
64        inspector_node.record_string("mlock_pin_flavor", &self.mlock_pin_flavor);
65        inspector_node
66            .record_uint("ui_visual_debugging_level", self.ui_visual_debugging_level as u64);
67    }
68}
69#[derive(Debug)]
70pub enum Error {
71    #[doc = r" Failed to read the content size of the VMO."]
72    GettingContentSize(zx::Status),
73    #[doc = r" Failed to read the content of the VMO."]
74    ReadingConfigBytes(zx::Status),
75    #[doc = r" The VMO was too small for this config library."]
76    TooFewBytes,
77    #[doc = r" The VMO's config ABI checksum did not match this library's."]
78    ChecksumMismatch { observed_checksum: Vec<u8> },
79    #[doc = r" Failed to parse the non-checksum bytes of the VMO as this library's FIDL type."]
80    Unpersist(fidl::Error),
81}
82impl std::fmt::Display for Error {
83    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
84        match self {
85            Self::GettingContentSize(status) => {
86                write!(f, "Failed to get content size: {status}")
87            }
88            Self::ReadingConfigBytes(status) => {
89                write!(f, "Failed to read VMO content: {status}")
90            }
91            Self::TooFewBytes => {
92                write!(f, "VMO content is not large enough for this config library.")
93            }
94            Self::ChecksumMismatch { observed_checksum } => {
95                write!(
96                    f,
97                    "ABI checksum mismatch, expected {:?}, got {:?}",
98                    EXPECTED_CHECKSUM, observed_checksum,
99                )
100            }
101            Self::Unpersist(fidl_error) => {
102                write!(f, "Failed to parse contents of config VMO: {fidl_error}")
103            }
104        }
105    }
106}
107impl std::error::Error for Error {
108    #[allow(unused_parens, reason = "rustfmt errors without parens here")]
109    fn source(&self) -> Option<(&'_ (dyn std::error::Error + 'static))> {
110        match self {
111            Self::GettingContentSize(ref status) | Self::ReadingConfigBytes(ref status) => {
112                Some(status)
113            }
114            Self::TooFewBytes => None,
115            Self::ChecksumMismatch { .. } => None,
116            Self::Unpersist(ref fidl_error) => Some(fidl_error),
117        }
118    }
119    fn description(&self) -> &str {
120        match self {
121            Self::GettingContentSize(_) => "getting content size",
122            Self::ReadingConfigBytes(_) => "reading VMO contents",
123            Self::TooFewBytes => "VMO contents too small",
124            Self::ChecksumMismatch { .. } => "ABI checksum mismatch",
125            Self::Unpersist(_) => "FIDL parsing error",
126        }
127    }
128}