1use crate::{Error, Value};
2use indexmap::IndexMap;
3use std::cmp::Ordering;
4use std::collections::BTreeMap;
5
6pub type ValueMap = Vec<(Value, Value)>;
7
8pub trait ValueMapHelper {
9 fn sort_by_keys(&mut self);
10 fn sort_by_keys_and_inner_maps(&mut self);
11 fn sort_by_lexicographical_byte_ordering_keys(&mut self);
12 fn sort_by_lexicographical_byte_ordering_keys_and_inner_maps(&mut self);
13 fn get_key(&self, search_key: &str) -> Result<&Value, Error>;
14 fn get_optional_key(&self, key: &str) -> Option<&Value>;
15 fn get_key_mut(&mut self, search_key: &str) -> Result<&mut Value, Error>;
16 fn get_optional_key_mut(&mut self, key: &str) -> Option<&mut Value>;
17 fn get_key_mut_or_insert(&mut self, key: &str, value: Value) -> &mut Value;
18 fn get_key_by_value_mut_or_insert(&mut self, search_key: &Value, value: Value) -> &mut Value;
19 fn insert_string_key_value(&mut self, key: String, value: Value);
20 fn remove_key(&mut self, search_key: &str) -> Result<Value, Error>;
21 fn remove_optional_key(&mut self, key: &str) -> Option<Value>;
22 fn remove_optional_key_if_null(&mut self, search_key: &str);
23 fn remove_optional_key_if_empty_array(&mut self, search_key: &str);
24 fn remove_optional_key_value(&mut self, search_key_value: &Value) -> Option<Value>;
25 fn from_btree_map<K: Into<Value> + Ord, V: Into<Value>>(btree_map: BTreeMap<K, V>) -> Self;
26}
27
28impl ValueMapHelper for ValueMap {
29 fn sort_by_keys(&mut self) {
30 self.sort_by(|(key1, _), (key2, _)| key1.partial_cmp(key2).unwrap_or(Ordering::Less));
31 }
32
33 fn sort_by_keys_and_inner_maps(&mut self) {
34 self.sort_by_keys();
35 self.iter_mut().for_each(|(_, v)| {
36 if let Value::Map(m) = v {
37 m.sort_by_keys_and_inner_maps()
38 }
39 });
40 }
41
42 fn sort_by_lexicographical_byte_ordering_keys(&mut self) {
43 self.sort_by(|(key1, _), (key2, _)| {
44 if key1.is_text() && key2.is_text() {
45 let key1 = key1.to_text().unwrap();
46 let key2 = key2.to_text().unwrap();
47 match key1.len().cmp(&key2.len()) {
48 Ordering::Less => Ordering::Less,
49 Ordering::Equal => key1.cmp(&key2),
50 Ordering::Greater => Ordering::Greater,
51 }
52 } else {
53 key1.partial_cmp(key2).unwrap_or(Ordering::Less)
54 }
55 })
56 }
57
58 fn sort_by_lexicographical_byte_ordering_keys_and_inner_maps(&mut self) {
59 self.sort_by_lexicographical_byte_ordering_keys();
60 self.iter_mut().for_each(|(_, v)| {
61 if let Value::Map(m) = v {
62 m.sort_by_lexicographical_byte_ordering_keys_and_inner_maps()
63 }
64 });
65 }
66
67 fn get_key(&self, search_key: &str) -> Result<&Value, Error> {
68 self.get_optional_key(search_key)
69 .ok_or(Error::StructureError(format!(
70 "required property not found {search_key}"
71 )))
72 }
73
74 fn get_optional_key(&self, search_key: &str) -> Option<&Value> {
75 self.iter().find_map(|(key, value)| {
76 if let Value::Text(text) = key {
77 if text == search_key {
78 Some(value)
79 } else {
80 None
81 }
82 } else {
83 None
84 }
85 })
86 }
87
88 fn get_key_mut(&mut self, search_key: &str) -> Result<&mut Value, Error> {
89 self.get_optional_key_mut(search_key)
90 .ok_or(Error::StructureError(format!(
91 "{search_key} not found, but was required"
92 )))
93 }
94
95 fn get_optional_key_mut(&mut self, search_key: &str) -> Option<&mut Value> {
96 self.iter_mut().find_map(|(key, value)| {
97 if let Value::Text(text) = key {
98 if text == search_key {
99 Some(value)
100 } else {
101 None
102 }
103 } else {
104 None
105 }
106 })
107 }
108
109 fn get_key_mut_or_insert(&mut self, search_key: &str, value: Value) -> &mut Value {
110 let found = self.iter().position(|(key, _)| {
111 if let Value::Text(text) = key {
112 text == search_key
113 } else {
114 false
115 }
116 });
117 match found {
118 None => {
119 self.push((Value::Text(search_key.to_string()), value));
120 let (_, value) = self.last_mut().unwrap();
121 value
122 }
123 Some(pos) => {
124 let (_, value) = self.get_mut(pos).unwrap();
125 value
126 }
127 }
128 }
129
130 fn get_key_by_value_mut_or_insert(&mut self, search_key: &Value, value: Value) -> &mut Value {
131 let found = self.iter().position(|(key, _)| search_key == key);
132 match found {
133 None => {
134 self.push((search_key.clone(), value));
135 let (_, value) = self.last_mut().unwrap();
136 value
137 }
138 Some(pos) => {
139 let (_, value) = self.get_mut(pos).unwrap();
140 value
141 }
142 }
143 }
144
145 fn insert_string_key_value(&mut self, key: String, value: Value) {
146 self.push((key.into(), value))
147 }
148
149 fn remove_key(&mut self, search_key: &str) -> Result<Value, Error> {
150 self.iter()
151 .position(|(key, _)| {
152 if let Value::Text(text) = key {
153 text == search_key
154 } else {
155 false
156 }
157 })
158 .map(|pos| self.remove(pos).1)
159 .ok_or(Error::StructureError(format!(
160 "trying to remove a key {} from a ValueMap that was not found",
161 search_key
162 )))
163 }
164
165 fn remove_optional_key(&mut self, search_key: &str) -> Option<Value> {
166 self.iter()
167 .position(|(key, _)| {
168 if let Value::Text(text) = key {
169 text == search_key
170 } else {
171 false
172 }
173 })
174 .map(|pos| self.remove(pos).1)
175 }
176
177 fn remove_optional_key_if_null(&mut self, search_key: &str) {
178 self.iter()
179 .position(|(key, value)| {
180 if let Value::Text(text) = key {
181 if text == search_key {
182 value.is_null()
183 } else {
184 false
185 }
186 } else {
187 false
188 }
189 })
190 .map(|pos| self.remove(pos).1);
191 }
192
193 fn remove_optional_key_if_empty_array(&mut self, search_key: &str) {
194 self.iter()
195 .position(|(key, value)| {
196 if let Value::Text(text) = key {
197 if text == search_key {
198 if let Some(v) = value.as_array() {
199 v.is_empty()
200 } else {
201 false
202 }
203 } else {
204 false
205 }
206 } else {
207 false
208 }
209 })
210 .map(|pos| self.remove(pos).1);
211 }
212
213 fn remove_optional_key_value(&mut self, search_key_value: &Value) -> Option<Value> {
214 self.iter()
215 .position(|(key, _)| search_key_value == key)
216 .map(|pos| self.remove(pos).1)
217 }
218 fn from_btree_map<K: Into<Value> + Ord, V: Into<Value>>(btree_map: BTreeMap<K, V>) -> Self {
219 btree_map
220 .into_iter()
221 .map(|(k, v)| (k.into(), v.into()))
222 .collect()
223 }
224}
225
226impl Value {
227 pub fn into_btree_string_map(self) -> Result<BTreeMap<String, Value>, Error> {
245 Self::map_into_btree_string_map(self.into_map()?)
246 }
247
248 pub fn to_btree_ref_string_map(&self) -> Result<BTreeMap<String, &Value>, Error> {
266 Self::map_ref_into_btree_string_map(self.to_map_ref()?)
267 }
268
269 pub fn to_ref_string_map<'a, I: FromIterator<(String, &'a Value)>>(
289 &'a self,
290 ) -> Result<I, Error> {
291 Self::map_ref_into_string_map(self.to_map_ref()?)
292 }
293
294 pub fn to_ref_string_map_mut<'a, I: FromIterator<(String, &'a mut Value)>>(
314 &'a mut self,
315 ) -> Result<I, Error> {
316 Self::map_mut_ref_into_string_map(self.as_map_mut_ref()?)
317 }
318
319 pub fn map_into_btree_string_map(map: ValueMap) -> Result<BTreeMap<String, Value>, Error> {
323 map.into_iter()
324 .map(|(key, value)| {
325 let key = key
326 .into_text()
327 .map_err(|_| Error::StructureError("expected key to be string".to_string()))?;
328 Ok((key, value))
329 })
330 .collect::<Result<BTreeMap<String, Value>, Error>>()
331 }
332
333 pub fn map_ref_into_btree_string_map(
337 map: &ValueMap,
338 ) -> Result<BTreeMap<String, &Value>, Error> {
339 map.iter()
340 .map(|(key, value)| {
341 let key = key
342 .to_text()
343 .map_err(|_| Error::StructureError("expected key to be string".to_string()))?;
344 Ok((key, value))
345 })
346 .collect::<Result<BTreeMap<String, &Value>, Error>>()
347 }
348
349 pub fn map_ref_into_indexed_string_map<'a, T>(
356 map: &'a ValueMap,
357 sort_key: &str,
358 ) -> Result<IndexMap<String, &'a Value>, Error>
359 where
360 T: TryFrom<i128>
361 + TryFrom<u128>
362 + TryFrom<u64>
363 + TryFrom<i64>
364 + TryFrom<u32>
365 + TryFrom<i32>
366 + TryFrom<u16>
367 + TryFrom<i16>
368 + TryFrom<u8>
369 + TryFrom<i8>
370 + Ord,
371 {
372 for (_, value) in map.iter() {
374 value.get_integer::<T>(sort_key)?;
375 }
376
377 let mut sorted_map: Vec<_> = map.iter().collect();
378
379 sorted_map.sort_by(|(_, value_1), (_, value_2)| {
380 let pos_1: T = value_1.get_integer(sort_key).expect("expected sort key");
381 let pos_2: T = value_2.get_integer(sort_key).expect("expected sort key");
382 pos_1.cmp(&pos_2)
383 });
384
385 sorted_map
386 .into_iter()
387 .map(|(key, value)| {
388 let key = key
389 .to_text()
390 .map_err(|_| Error::StructureError("expected key to be string".to_string()))?;
391 Ok((key, value))
392 })
393 .collect::<Result<IndexMap<String, &Value>, Error>>()
394 }
395
396 pub fn map_ref_into_string_map<'a, I: FromIterator<(String, &'a Value)>>(
400 map: &'a ValueMap,
401 ) -> Result<I, Error> {
402 map.iter()
403 .map(|(key, value)| {
404 let key = key
405 .to_text()
406 .map_err(|_| Error::StructureError("expected key to be string".to_string()))?;
407 Ok((key, value))
408 })
409 .collect::<Result<I, Error>>()
410 }
411
412 pub fn map_mut_ref_into_string_map<'a, I: FromIterator<(String, &'a mut Value)>>(
416 map: &'a mut ValueMap,
417 ) -> Result<I, Error> {
418 map.iter_mut()
419 .map(|(key, value)| {
420 let key = key
421 .to_text()
422 .map_err(|_| Error::StructureError("expected key to be string".to_string()))?;
423 Ok((key, value))
424 })
425 .collect::<Result<I, Error>>()
426 }
427}