salak/
source_yaml.rs

1use yaml_rust::Yaml;
2
3use crate::{
4    source_raw::FileItem, Key, Property, PropertyError, PropertySource, Res, SubKey, SubKeys,
5};
6
7pub(crate) struct YamlValue {
8    item: FileItem,
9    name: String,
10    value: Vec<Yaml>,
11}
12
13impl YamlValue {
14    pub(crate) fn new(item: FileItem) -> Res<Self> {
15        Ok(Self {
16            name: item.name(),
17            value: yaml_rust::YamlLoader::load_from_str(&item.load()?)?,
18            item,
19        })
20    }
21}
22
23fn sub_value<'a>(mut val: &'a Yaml, key: &Key<'_>) -> Option<&'a Yaml> {
24    for n in key.iter() {
25        match n {
26            SubKey::S(n) => match val {
27                Yaml::Hash(t) => val = t.get(&Yaml::String(n.to_string()))?,
28                _ => return None,
29            },
30            SubKey::I(n) => match val {
31                Yaml::Array(vs) => val = vs.get(*n)?,
32                _ => return None,
33            },
34        }
35    }
36    Some(val)
37}
38
39impl PropertySource for YamlValue {
40    fn name(&self) -> &str {
41        &self.name
42    }
43
44    fn get_property(&self, key: &Key<'_>) -> Option<Property<'_>> {
45        for v in &self.value {
46            if let Some(v) = sub_value(v, key) {
47                return match v {
48                    Yaml::String(vs) => Some(Property::S(vs)),
49                    Yaml::Integer(vs) => Some(Property::I(*vs)),
50                    Yaml::Real(vs) => Some(Property::S(vs)),
51                    Yaml::Boolean(vs) => Some(Property::B(*vs)),
52                    _ => continue,
53                };
54            }
55        }
56        None
57    }
58
59    fn get_sub_keys<'a>(&'a self, key: &Key<'_>, sub_keys: &mut SubKeys<'a>) {
60        for v in &self.value {
61            if let Some(v) = sub_value(v, key) {
62                match v {
63                    Yaml::Hash(t) => t.keys().for_each(|f| {
64                        if let Some(v) = f.as_str() {
65                            sub_keys.insert(v);
66                        }
67                    }),
68                    Yaml::Array(vs) => sub_keys.insert(vs.len()),
69                    _ => continue,
70                }
71            }
72        }
73    }
74
75    fn is_empty(&self) -> bool {
76        for v in &self.value {
77            return match v {
78                Yaml::Hash(t) => t.is_empty(),
79                _ => continue,
80            };
81        }
82        false
83    }
84
85    fn reload_source(&self) -> Result<Option<Box<dyn PropertySource>>, PropertyError> {
86        Ok(Some(Box::new(YamlValue::new(self.item.clone())?)))
87    }
88}