verifyos_cli/parsers/
plist_reader.rs1use 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 from_dictionary(dict: plist::Dictionary) -> Self {
34 Self {
35 root: Value::Dictionary(dict),
36 }
37 }
38
39 pub fn get_string(&self, key: &str) -> Option<&str> {
40 self.root
41 .as_dictionary()
42 .and_then(|dict| dict.get(key))
43 .and_then(|v| v.as_string())
44 }
45
46 pub fn get_bool(&self, key: &str) -> Option<bool> {
47 self.root
48 .as_dictionary()
49 .and_then(|dict| dict.get(key))
50 .and_then(|v| v.as_boolean())
51 }
52
53 pub fn has_key(&self, key: &str) -> bool {
54 self.root
55 .as_dictionary()
56 .map(|dict| dict.contains_key(key))
57 .unwrap_or(false)
58 }
59
60 pub fn get_dictionary(&self, key: &str) -> Option<&plist::Dictionary> {
61 self.root
62 .as_dictionary()
63 .and_then(|dict| dict.get(key))
64 .and_then(|v| v.as_dictionary())
65 }
66
67 pub fn get_value(&self, key: &str) -> Option<&Value> {
68 self.root.as_dictionary().and_then(|dict| dict.get(key))
69 }
70
71 pub fn get_array_strings(&self, key: &str) -> Option<Vec<String>> {
72 self.root
73 .as_dictionary()
74 .and_then(|dict| dict.get(key))
75 .and_then(|v| v.as_array())
76 .map(|arr| {
77 arr.iter()
78 .filter_map(|v| v.as_string().map(|s| s.to_string()))
79 .collect()
80 })
81 }
82}