toml_input/
value.rs

1use toml::{Value as TomlValue, map::Map};
2
3use crate::util;
4#[derive(Debug, Clone, Default)]
5pub struct BlockValue {
6    pub key: String,
7    pub tag: String,
8    pub value: Option<TomlValue>,
9    pub array_index: Option<usize>,
10}
11
12#[derive(Debug, Clone, Default)]
13pub struct PrimValue {
14    pub tag: String,
15    pub raw: Option<TomlValue>,
16}
17
18impl PrimValue {
19    pub fn new(raw: TomlValue) -> Self {
20        PrimValue {
21            raw: Some(raw),
22            ..Default::default()
23        }
24    }
25    pub fn flatten(self) -> BlockValue {
26        let PrimValue { tag, raw } = self;
27        BlockValue {
28            tag,
29            value: raw,
30            ..Default::default()
31        }
32    }
33}
34
35#[derive(Debug, Clone, Default)]
36pub struct ArrayValue {
37    pub values: Vec<Value>,
38}
39
40impl ArrayValue {
41    pub fn into_prim(self) -> PrimValue {
42        let mut raws = Vec::new();
43        for value in self.values {
44            let PrimValue { raw, .. } = value.into_prim();
45            if let Some(raw) = raw {
46                raws.push(raw);
47            }
48        }
49        PrimValue {
50            tag: String::new(),
51            raw: Some(TomlValue::Array(raws)),
52        }
53    }
54
55    pub fn flatten(self) -> Vec<BlockValue> {
56        let ArrayValue { values, .. } = self;
57        let mut blocks = Vec::new();
58        for (i, value) in values.into_iter().enumerate() {
59            let tmp = value.flatten();
60            for mut block in tmp {
61                block.array_index = Some(i);
62                blocks.push(block);
63            }
64        }
65        blocks
66    }
67}
68
69#[derive(Debug, Clone, Default)]
70pub struct TableValue {
71    pub fields: Vec<FieldValue>,
72}
73
74impl TableValue {
75    pub fn into_prim(self) -> PrimValue {
76        let mut map = Map::new();
77        for field in self.fields {
78            for (key, value) in field.into_map() {
79                map.insert(key, value);
80            }
81        }
82        PrimValue {
83            tag: String::new(),
84            raw: Some(TomlValue::Table(map)),
85        }
86    }
87
88    pub fn flatten(self) -> Vec<BlockValue> {
89        let TableValue { fields, .. } = self;
90        let mut values = Vec::new();
91        for field in fields {
92            values.append(&mut field.flatten());
93        }
94        values
95    }
96}
97
98#[derive(Debug, Clone)]
99pub enum Value {
100    Prim(PrimValue),
101    Array(ArrayValue),
102    Table(TableValue),
103}
104
105impl Default for Value {
106    fn default() -> Self {
107        Value::Prim(PrimValue::default())
108    }
109}
110
111impl Value {
112    pub fn new_prim(raw: TomlValue) -> Self {
113        let prim = PrimValue::new(raw);
114        Value::Prim(prim)
115    }
116
117    pub fn into_prim(self) -> PrimValue {
118        match self {
119            Value::Prim(prim) => prim,
120            Value::Array(array) => array.into_prim(),
121            Value::Table(table) => table.into_prim(),
122        }
123    }
124
125    pub fn is_prim(&self) -> bool {
126        matches!(self, Value::Prim(_))
127    }
128
129    pub fn is_array(&self) -> bool {
130        matches!(self, Value::Array(_))
131    }
132
133    pub fn is_table(&self) -> bool {
134        matches!(self, Value::Table(_))
135    }
136
137    pub fn flatten(self) -> Vec<BlockValue> {
138        match self {
139            Value::Prim(prim) => vec![prim.flatten()],
140            Value::Array(array) => array.flatten(),
141            Value::Table(table) => table.flatten(),
142        }
143    }
144}
145
146#[derive(Debug, Clone, Default)]
147pub struct FieldValue {
148    pub ident: String,
149    pub value: Value,
150    pub flat: bool,
151}
152
153impl FieldValue {
154    pub fn into_map(self) -> Map<String, TomlValue> {
155        let FieldValue { ident, value, flat } = self;
156        let PrimValue { raw, .. } = value.into_prim();
157        let mut map = Map::new();
158        if flat {
159            if let Some(TomlValue::Table(map)) = raw {
160                return map;
161            }
162        }
163        if let Some(raw) = raw {
164            map.insert(ident, raw);
165        }
166        map
167    }
168    pub fn flatten(self) -> Vec<BlockValue> {
169        let FieldValue { ident, value, flat } = self;
170        let mut blocks = value.flatten();
171        if !flat {
172            for block in &mut blocks {
173                util::increase_key(&mut block.key, &ident);
174            }
175        }
176        blocks
177    }
178}