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