1use super::YamlTypes;
2use super::{AliasedYaml, HashData, HashElement, Yaml};
3use crate::YamlPath;
4use std::collections::BTreeMap;
5use std::ops::Fn;
6
7pub trait Additive: std::ops::Add<Output = Self> + Sized {
8 fn zero() -> Self;
9}
10
11impl Additive for usize {
12 fn zero() -> Self {
13 0
14 }
15}
16
17#[derive(Debug, PartialEq)]
18pub struct MyVec<T>(pub Vec<T>);
19
20impl<T> std::ops::Add<MyVec<T>> for MyVec<T> {
21 type Output = Self;
22 fn add(self, rhs: MyVec<T>) -> Self::Output {
23 Self(self.0.into_iter().chain(rhs.0.into_iter()).collect())
24 }
25}
26
27impl<T> Additive for MyVec<T> {
28 fn zero() -> Self {
29 Self(Vec::new())
30 }
31}
32
33pub trait YamlInsert {
34 fn for_hash<F, R, A: Additive>(&mut self, path: &YamlPath, f: &F, r: &R) -> A
35 where
36 F: Fn(&mut HashElement) -> A,
37 R: Fn(&mut Yaml) -> A;
38
39 fn edit_hash_structure<F>(&mut self, path: &YamlPath, f: &F) -> usize
40 where
41 F: Fn(&mut Vec<HashData>, String, Option<usize>) -> usize;
42
43 fn find_values(&mut self, path: &YamlPath) -> MyVec<Yaml> {
45 let f = |e: &mut HashElement| MyVec(vec![e.value.value.clone()]);
46 let r = |hash: &mut Yaml| MyVec(vec![hash.clone()]);
47 self.for_hash(&path, &f, &r)
48 }
49
50 fn insert_into_hash(&mut self, path: &YamlPath, h: &AliasedYaml, overwrite: bool) -> usize {
54 let f = |data: &mut Vec<HashData>, key: String, key_index: Option<usize>| {
55 let value = HashData::Element(HashElement {
56 key,
57 value: h.to_owned(),
58 });
59 if key_index.is_none() {
60 data.push(value);
61 1
62 } else if let Some(index) = key_index {
63 if overwrite {
64 data[index] = value;
65 1
66 } else {
67 0
68 }
69 } else {
70 0
71 }
72 };
73 self.edit_hash_structure(path, &f)
74 }
75
76 fn insert_into_hash_by_call<F>(&mut self, path: &YamlPath, h: F, overwrite: bool) -> usize
77 where
78 F: Fn() -> AliasedYaml,
79 {
80 let f = |data: &mut Vec<HashData>, key: String, key_index: Option<usize>| {
81 let value = HashData::Element(HashElement { key, value: h() });
82 if key_index.is_none() {
83 data.push(value);
84 1
85 } else if let Some(index) = key_index {
86 if overwrite {
87 data[index] = value;
88 1
89 } else {
90 0
91 }
92 } else {
93 0
94 }
95 };
96 self.edit_hash_structure(path, &f)
97 }
98 fn remove_from_hash(&mut self, path: &YamlPath) -> usize {
99 let f = |data: &mut Vec<HashData>, _key: String, key_index: Option<usize>| {
100 if let Some(index) = key_index {
101 data.remove(index);
102 1
103 } else {
104 0
105 }
106 };
107 self.edit_hash_structure(path, &f)
108 }
109 fn rename_field(&mut self, path: &YamlPath, new_name: String) -> usize {
110 let f = |e: &mut HashElement| {
111 e.key = new_name.clone();
112 1
113 };
114 let r = |_hash: &mut Yaml| 0;
115 self.for_hash(&path, &f, &r)
116 }
117 fn to_object(&mut self, path: &YamlPath, object_key: String) -> usize {
118 let f = |e: &mut HashElement| {
119 let val = e.value.clone();
120 let new = AliasedYaml {
121 alias: None,
122 value: Yaml::Hash(vec![HashData::Element(HashElement {
123 key: object_key.clone(),
124 value: val,
125 })]),
126 };
127 e.value = new;
128 1
129 };
130 let r = |_hash: &mut Yaml| 0;
131 self.for_hash(&path, &f, &r)
132 }
133 fn move_to_subfield(
134 &mut self,
135 path: &YamlPath,
136 subfield: String,
137 fields_to_move: Vec<String>,
138 ) -> usize {
139 let r = |hash: &mut Yaml| match hash {
140 Yaml::Hash(_data) => {
141 let fields: Vec<_> = fields_to_move
142 .iter()
143 .filter_map(|key| hash.key_value_owned(key).map(|val| (key, val)))
144 .collect();
145 if !fields.is_empty() {
146 let subfield_value_opt = hash.key_value_mut(&subfield);
147 let res = if let Some(subfield_value) = subfield_value_opt {
148 for (key, value) in fields.iter() {
149 let path = key.parse().unwrap();
150 subfield_value.insert_into_hash(&path, &value, true);
151 }
152 1
153 } else {
154 let value = Yaml::Hash(
155 fields
156 .clone()
157 .into_iter()
158 .map(|(key, value)| {
159 HashData::Element(HashElement {
160 key: key.clone(),
161 value: value.clone(),
162 })
163 })
164 .collect(),
165 );
166 let new = AliasedYaml { alias: None, value };
167 hash.insert_into_hash(&subfield.parse().unwrap(), &new, false);
168 1
169 };
170 for (key, _) in fields {
171 hash.remove_from_hash(&key.parse().unwrap());
172 }
173 res
174 } else {
175 0
176 }
177 }
178 _ => 0,
179 };
180 let f = |e: &mut HashElement| {
181 let hash = &mut e.value.value;
182 r(hash)
183 };
184
185 self.for_hash(&path, &f, &r)
186 }
187 fn move_to_map_with_field_as_key(
188 &mut self,
189 path: &YamlPath,
190 old_map_name: String,
191 selector: String,
192 new_map_name: String,
193 keeps: Vec<String>,
194 ) -> usize {
195 let r = |hash: &mut Yaml| match hash {
196 Yaml::Hash(_data) => {
197 if let Some(result) = hash.key_value_owned(&old_map_name) {
198 if let Yaml::Hash(hash_data) = result.value {
199 let mut new_hashes: BTreeMap<String, Vec<HashData>> = BTreeMap::new();
200 let mut old_hashes = Vec::new();
201 let mut comments = Vec::new();
202 let mut last_added_to = None;
203 for mut hash_data in hash_data {
204 match hash_data {
205 HashData::Element(ref hash_element) => {
206 if let Some(key) =
207 hash_element.value.value.key_value_owned(&selector)
208 {
209 if let Some(s) = key.as_string() {
210 if keeps.contains(&s) || s.is_empty() {
211 hash_data
212 .remove_from_hash(&selector.parse().unwrap());
213 old_hashes.extend(comments.clone());
214 comments.clear();
215 old_hashes.push(hash_data);
216 last_added_to = None
217 } else {
218 let mut value = hash_element.value.clone();
219 value.remove_from_hash(&selector.parse().unwrap());
220
221 let new_hash_element =
222 HashData::Element(HashElement {
223 key: hash_element.key.clone(),
224 value,
225 });
226
227 if new_hashes.contains_key(&s) {
228 let i = new_hashes.get_mut(&s).unwrap();
229 i.extend(comments.clone());
230 i.push(new_hash_element);
231 comments.clear();
232 } else {
233 let mut items = comments.clone();
234 items.push(new_hash_element);
235 new_hashes.insert(s.clone(), items);
236 comments.clear();
237 }
238 last_added_to = Some(s);
239 }
240 } else {
241 old_hashes.extend(comments.clone());
242 comments.clear();
243 old_hashes.push(hash_data);
244 last_added_to = None
245 }
246 } else {
247 old_hashes.extend(comments.clone());
248 comments.clear();
249 old_hashes.push(hash_data);
250 last_added_to = None
251 }
252 }
253 HashData::Comment(_) | HashData::InlineComment(_) => {
254 comments.push(hash_data)
255 }
256 }
257 }
258 if let Some(s) = last_added_to {
259 new_hashes.get_mut(&s).unwrap().extend(comments);
260 } else {
261 old_hashes.extend(comments);
262 }
263 if !new_hashes.is_empty() {
264 let new = AliasedYaml {
265 alias: result.alias.clone(),
266 value: Yaml::Hash(
267 new_hashes
268 .into_iter()
269 .map(|(key, value)| {
270 HashData::Element(HashElement {
271 key: key.clone(),
272 value: AliasedYaml {
273 alias: None,
274 value: Yaml::Hash(value),
275 },
276 })
277 })
278 .collect(),
279 ),
280 };
281 hash.insert_into_hash(&new_map_name.parse().unwrap(), &new, false);
282 let old = AliasedYaml {
283 alias: result.alias.clone(),
284 value: Yaml::Hash(old_hashes),
285 };
286 hash.insert_into_hash(&old_map_name.parse().unwrap(), &old, true);
287 1
288 } else {
289 0
290 }
291 } else {
292 0
293 }
294 } else {
295 0
296 }
297 }
298 _ => 0,
299 };
300 let f = |e: &mut HashElement| {
301 let hash = &mut e.value.value;
302 r(hash)
303 };
304
305 self.for_hash(&path, &f, &r)
306 }
307}