ligen_parser/parser/config/
group.rs

1use std::collections::HashMap;
2
3use ligen_ir::{Literal, Path};
4
5use crate::prelude::*;
6
7#[derive(Debug, Serialize, Deserialize, Clone)]
8#[serde(untagged)]
9pub enum Value {
10    Literal(Literal),
11    Group(Group)
12}
13
14#[derive(Debug, Default, Serialize, Deserialize, Clone)]
15pub struct Group {
16    #[serde(flatten)]
17    map: HashMap<String, Value>
18}
19
20impl Group {
21    pub fn iter(&self) -> impl Iterator<Item = (Path, Literal)> {
22        self.map
23            .clone()
24            .into_iter()
25            .flat_map(|(key, value)| {
26                match value {
27                    Value::Literal(literal) => {
28                        vec![(Path::from(key), literal)]
29                    },
30                    Value::Group(group) => {
31                        group
32                            .iter()
33                            .map(|(path, literal)| {
34                                let mut path = path.clone();
35                                path.push_front(key.clone());
36                                (path, literal.clone())
37                            })
38                            .collect()
39                    }
40                }
41            })
42    }
43}
44
45impl Group {
46    /// Sets the value at the given path.
47    pub fn set<P: Into<Path>, L: Into<Literal>>(&mut self, path: P, value: L) {
48        let mut path = path.into();
49        if let Some(word) = path.pop_front() {
50            if path.is_empty() {
51                self.map.insert(word.identifier.name, Value::Literal(value.into()));
52            } else {
53                let group = self.map
54                    .entry(word.identifier.name)
55                    .or_insert_with(|| Value::Group(Group::default()));
56                if let Value::Group(group) = group {
57                    group.set(path, value);
58                }
59            }
60        }
61    }
62
63    /// Gets the value at the given path.
64    pub fn get<P: Into<Path>>(&self, path: P) -> Option<&Literal> {
65        let mut path = path.into();
66        if let Some(word) = path.pop_front() {
67            match self
68                .map
69                .get(&word.identifier.name) {
70                Some(Value::Literal(literal)) => {
71                    if path.is_empty() {
72                        Some(literal)
73                    } else {
74                        None
75                    }
76                },
77                Some(Value::Group(group)) => group.get(path),
78                None => None
79            }
80        } else {
81            None
82        }
83    }
84}