Skip to main content

verifyos_cli/parsers/
plist_reader.rs

1use plist::Value;
2use std::path::Path;
3
4#[derive(Debug, thiserror::Error)]
5pub enum PlistError {
6    #[error("Plist Error: {0}")]
7    ParseError(#[from] plist::Error),
8    #[error("Not a dictionary")]
9    NotADictionary,
10}
11
12pub struct InfoPlist {
13    pub root: Value,
14}
15
16impl InfoPlist {
17    pub fn from_file<P: AsRef<Path>>(path: P) -> Result<Self, PlistError> {
18        let value = Value::from_file(path)?;
19        if value.as_dictionary().is_none() {
20            return Err(PlistError::NotADictionary);
21        }
22        Ok(Self { root: value })
23    }
24
25    pub fn from_bytes(bytes: &[u8]) -> Result<Self, PlistError> {
26        let value = Value::from_reader(std::io::Cursor::new(bytes))?;
27        if value.as_dictionary().is_none() {
28            return Err(PlistError::NotADictionary);
29        }
30        Ok(Self { root: value })
31    }
32
33    pub fn get_string(&self, key: &str) -> Option<&str> {
34        self.root
35            .as_dictionary()
36            .and_then(|dict| dict.get(key))
37            .and_then(|v| v.as_string())
38    }
39
40    pub fn get_bool(&self, key: &str) -> Option<bool> {
41        self.root
42            .as_dictionary()
43            .and_then(|dict| dict.get(key))
44            .and_then(|v| v.as_boolean())
45    }
46
47    pub fn has_key(&self, key: &str) -> bool {
48        self.root
49            .as_dictionary()
50            .map(|dict| dict.contains_key(key))
51            .unwrap_or(false)
52    }
53}