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
226#[cfg(test)]
227#[allow(clippy::items_after_test_module)]
228mod tests {
229 use super::*;
230
231 fn text(s: &str) -> Value {
232 Value::Text(s.to_string())
233 }
234
235 fn make_map(pairs: &[(&str, Value)]) -> ValueMap {
236 pairs.iter().map(|(k, v)| (text(k), v.clone())).collect()
237 }
238
239 #[test]
244 fn sort_by_keys_mixed_text_keys() {
245 let mut map = make_map(&[
246 ("c", Value::U32(3)),
247 ("a", Value::U32(1)),
248 ("b", Value::U32(2)),
249 ]);
250 map.sort_by_keys();
251 let keys: Vec<_> = map.iter().map(|(k, _)| k.clone()).collect();
252 assert_eq!(keys, vec![text("a"), text("b"), text("c")]);
253 }
254
255 #[test]
256 fn sort_by_keys_mixed_types() {
257 let mut map: ValueMap = vec![
259 (text("z"), Value::U32(1)),
260 (Value::U32(5), Value::U32(2)),
261 (text("a"), Value::U32(3)),
262 ];
263 map.sort_by_keys();
264 assert_eq!(map[0].0, Value::U32(5));
266 assert_eq!(map[1].0, text("a"));
267 assert_eq!(map[2].0, text("z"));
268 }
269
270 #[test]
275 fn sort_by_lexicographical_byte_ordering_shorter_first() {
276 let mut map = make_map(&[
278 ("abc", Value::U32(1)),
279 ("ab", Value::U32(2)),
280 ("a", Value::U32(3)),
281 ]);
282 map.sort_by_lexicographical_byte_ordering_keys();
283 let keys: Vec<_> = map.iter().map(|(k, _)| k.to_text().unwrap()).collect();
284 assert_eq!(keys, vec!["a", "ab", "abc"]);
285 }
286
287 #[test]
288 fn sort_by_lexicographical_byte_ordering_same_length_alphabetical() {
289 let mut map = make_map(&[
290 ("cb", Value::U32(1)),
291 ("ab", Value::U32(2)),
292 ("bb", Value::U32(3)),
293 ]);
294 map.sort_by_lexicographical_byte_ordering_keys();
295 let keys: Vec<_> = map.iter().map(|(k, _)| k.to_text().unwrap()).collect();
296 assert_eq!(keys, vec!["ab", "bb", "cb"]);
297 }
298
299 #[test]
300 fn sort_by_lexicographical_byte_ordering_non_text_keys_uses_partial_cmp() {
301 let mut map: ValueMap = vec![(Value::U32(10), Value::Null), (Value::U32(2), Value::Null)];
302 map.sort_by_lexicographical_byte_ordering_keys();
303 assert_eq!(map[0].0, Value::U32(2));
304 assert_eq!(map[1].0, Value::U32(10));
305 }
306
307 #[test]
312 fn get_key_mut_or_insert_inserts_new() {
313 let mut map = make_map(&[("a", Value::U32(1))]);
314 let val = map.get_key_mut_or_insert("b", Value::U32(99));
315 assert_eq!(*val, Value::U32(99));
316 *val = Value::U32(100);
318 assert_eq!(map.get_optional_key("b"), Some(&Value::U32(100)));
319 }
320
321 #[test]
322 fn get_key_mut_or_insert_returns_existing() {
323 let mut map = make_map(&[("a", Value::U32(1))]);
324 let val = map.get_key_mut_or_insert("a", Value::U32(99));
325 assert_eq!(*val, Value::U32(1));
327 }
328
329 #[test]
330 fn get_key_mut_or_insert_existing_is_mutable() {
331 let mut map = make_map(&[("a", Value::U32(1))]);
332 let val = map.get_key_mut_or_insert("a", Value::U32(99));
333 *val = Value::U32(42);
334 assert_eq!(map.get_optional_key("a"), Some(&Value::U32(42)));
335 }
336
337 #[test]
342 fn remove_optional_key_if_null_removes_null() {
343 let mut map = make_map(&[("a", Value::Null), ("b", Value::U32(2))]);
344 map.remove_optional_key_if_null("a");
345 assert_eq!(map.get_optional_key("a"), None);
346 assert_eq!(map.get_optional_key("b"), Some(&Value::U32(2)));
347 }
348
349 #[test]
350 fn remove_optional_key_if_null_keeps_non_null() {
351 let mut map = make_map(&[("a", Value::U32(1))]);
352 map.remove_optional_key_if_null("a");
353 assert_eq!(map.get_optional_key("a"), Some(&Value::U32(1)));
354 }
355
356 #[test]
357 fn remove_optional_key_if_null_missing_key_is_noop() {
358 let mut map = make_map(&[("a", Value::U32(1))]);
359 map.remove_optional_key_if_null("missing");
360 assert_eq!(map.len(), 1);
361 }
362
363 #[test]
368 fn remove_optional_key_if_empty_array_removes_empty() {
369 let mut map = make_map(&[("a", Value::Array(vec![])), ("b", Value::U32(1))]);
370 map.remove_optional_key_if_empty_array("a");
371 assert_eq!(map.get_optional_key("a"), None);
372 assert_eq!(map.get_optional_key("b"), Some(&Value::U32(1)));
373 }
374
375 #[test]
376 fn remove_optional_key_if_empty_array_keeps_non_empty() {
377 let mut map = make_map(&[("a", Value::Array(vec![Value::U32(1)]))]);
378 map.remove_optional_key_if_empty_array("a");
379 assert!(map.get_optional_key("a").is_some());
380 }
381
382 #[test]
383 fn remove_optional_key_if_empty_array_keeps_non_array() {
384 let mut map = make_map(&[("a", Value::U32(42))]);
385 map.remove_optional_key_if_empty_array("a");
386 assert_eq!(map.get_optional_key("a"), Some(&Value::U32(42)));
387 }
388
389 #[test]
390 fn remove_optional_key_if_empty_array_missing_key_is_noop() {
391 let mut map = make_map(&[("a", Value::U32(1))]);
392 map.remove_optional_key_if_empty_array("missing");
393 assert_eq!(map.len(), 1);
394 }
395
396 #[test]
401 fn into_btree_string_map_valid_conversion() {
402 let val = Value::Map(make_map(&[("b", Value::U32(2)), ("a", Value::U32(1))]));
403 let btree = val.into_btree_string_map().unwrap();
404 assert_eq!(btree.get("a"), Some(&Value::U32(1)));
405 assert_eq!(btree.get("b"), Some(&Value::U32(2)));
406 let keys: Vec<_> = btree.keys().collect();
408 assert_eq!(keys, vec!["a", "b"]);
409 }
410
411 #[test]
412 fn into_btree_string_map_error_on_non_string_keys() {
413 let val = Value::Map(vec![(Value::U32(1), Value::U32(2))]);
414 let result = val.into_btree_string_map();
415 assert!(result.is_err());
416 }
417
418 #[test]
419 fn into_btree_string_map_error_on_non_map() {
420 let val = Value::Bool(true);
421 let result = val.into_btree_string_map();
422 assert!(result.is_err());
423 }
424
425 #[test]
430 fn map_ref_into_indexed_string_map_sorts_by_integer_key() {
431 let map: ValueMap = vec![
432 (
433 text("second"),
434 Value::Map(make_map(&[("pos", Value::U32(2))])),
435 ),
436 (
437 text("first"),
438 Value::Map(make_map(&[("pos", Value::U32(1))])),
439 ),
440 (
441 text("third"),
442 Value::Map(make_map(&[("pos", Value::U32(3))])),
443 ),
444 ];
445 let indexed = Value::map_ref_into_indexed_string_map::<u32>(&map, "pos").unwrap();
446 let keys: Vec<_> = indexed.keys().collect();
447 assert_eq!(keys, vec!["first", "second", "third"]);
448 }
449
450 #[test]
451 fn map_ref_into_indexed_string_map_error_missing_sort_key() {
452 let map: ValueMap = vec![(
453 text("item"),
454 Value::Map(make_map(&[("other", Value::U32(1))])),
455 )];
456 let result = Value::map_ref_into_indexed_string_map::<u32>(&map, "pos");
457 assert!(result.is_err());
458 }
459
460 #[test]
465 fn get_key_found() {
466 let map = make_map(&[("x", Value::U32(42))]);
467 let val = map.get_key("x").unwrap();
468 assert_eq!(*val, Value::U32(42));
469 }
470
471 #[test]
472 fn get_key_not_found_errors() {
473 let map = make_map(&[("x", Value::U32(42))]);
474 assert!(map.get_key("y").is_err());
475 }
476
477 #[test]
478 fn get_optional_key_none_for_missing() {
479 let map = make_map(&[("x", Value::U32(42))]);
480 assert_eq!(map.get_optional_key("y"), None);
481 }
482
483 #[test]
484 fn get_optional_key_ignores_non_text_keys() {
485 let map: ValueMap = vec![(Value::U32(1), Value::U32(2))];
486 assert_eq!(map.get_optional_key("1"), None);
487 }
488
489 #[test]
494 fn remove_key_success() {
495 let mut map = make_map(&[("a", Value::U32(1)), ("b", Value::U32(2))]);
496 let removed = map.remove_key("a").unwrap();
497 assert_eq!(removed, Value::U32(1));
498 assert_eq!(map.len(), 1);
499 }
500
501 #[test]
502 fn remove_key_not_found_errors() {
503 let mut map = make_map(&[("a", Value::U32(1))]);
504 assert!(map.remove_key("missing").is_err());
505 }
506
507 #[test]
508 fn remove_optional_key_returns_none_for_missing() {
509 let mut map = make_map(&[("a", Value::U32(1))]);
510 assert_eq!(map.remove_optional_key("missing"), None);
511 }
512
513 #[test]
514 fn remove_optional_key_returns_value() {
515 let mut map = make_map(&[("a", Value::U32(1))]);
516 assert_eq!(map.remove_optional_key("a"), Some(Value::U32(1)));
517 assert!(map.is_empty());
518 }
519
520 #[test]
525 fn remove_optional_key_value_by_value_key() {
526 let mut map: ValueMap = vec![
527 (Value::U32(10), Value::Bool(true)),
528 (text("x"), Value::Bool(false)),
529 ];
530 let removed = map.remove_optional_key_value(&Value::U32(10));
531 assert_eq!(removed, Some(Value::Bool(true)));
532 assert_eq!(map.len(), 1);
533 }
534
535 #[test]
536 fn remove_optional_key_value_not_found() {
537 let mut map = make_map(&[("a", Value::U32(1))]);
538 assert_eq!(map.remove_optional_key_value(&Value::U32(99)), None);
539 }
540
541 #[test]
546 fn insert_string_key_value_appends() {
547 let mut map: ValueMap = vec![];
548 map.insert_string_key_value("hello".to_string(), Value::Bool(true));
549 assert_eq!(map.len(), 1);
550 assert_eq!(map.get_optional_key("hello"), Some(&Value::Bool(true)));
551 }
552
553 #[test]
558 fn from_btree_map_preserves_entries() {
559 let mut btree = BTreeMap::new();
560 btree.insert("b".to_string(), Value::U32(2));
561 btree.insert("a".to_string(), Value::U32(1));
562 let map = ValueMap::from_btree_map(btree);
563 assert_eq!(map.len(), 2);
564 assert_eq!(map.get_optional_key("a"), Some(&Value::U32(1)));
565 assert_eq!(map.get_optional_key("b"), Some(&Value::U32(2)));
566 }
567
568 #[test]
573 fn get_key_by_value_mut_or_insert_inserts_new() {
574 let mut map: ValueMap = vec![];
575 let val = map.get_key_by_value_mut_or_insert(&Value::U32(42), Value::Bool(true));
576 assert_eq!(*val, Value::Bool(true));
577 assert_eq!(map.len(), 1);
578 }
579
580 #[test]
581 fn get_key_by_value_mut_or_insert_returns_existing() {
582 let mut map: ValueMap = vec![(Value::U32(42), Value::Bool(false))];
583 let val = map.get_key_by_value_mut_or_insert(&Value::U32(42), Value::Bool(true));
584 assert_eq!(*val, Value::Bool(false));
585 }
586
587 #[test]
592 fn sort_by_keys_and_inner_maps_sorts_recursively() {
593 let inner = make_map(&[("z", Value::U32(1)), ("a", Value::U32(2))]);
594 let mut map = make_map(&[("b", Value::Map(inner)), ("a", Value::U32(3))]);
595 map.sort_by_keys_and_inner_maps();
596 assert_eq!(map[0].0, text("a"));
598 assert_eq!(map[1].0, text("b"));
599 if let Value::Map(ref inner) = map[1].1 {
601 assert_eq!(inner[0].0, text("a"));
602 assert_eq!(inner[1].0, text("z"));
603 } else {
604 panic!("expected inner map");
605 }
606 }
607
608 #[test]
613 fn to_btree_ref_string_map_valid() {
614 let val = Value::Map(make_map(&[("x", Value::U32(10))]));
615 let btree = val.to_btree_ref_string_map().unwrap();
616 assert_eq!(btree.get("x"), Some(&&Value::U32(10)));
617 }
618
619 #[test]
620 fn to_btree_ref_string_map_error_on_non_map() {
621 let val = Value::U32(1);
622 assert!(val.to_btree_ref_string_map().is_err());
623 }
624
625 #[test]
626 fn to_btree_ref_string_map_error_on_non_string_key() {
627 let val = Value::Map(vec![(Value::U32(1), Value::U32(2))]);
628 assert!(val.to_btree_ref_string_map().is_err());
629 }
630}
631
632impl Value {
633 pub fn into_btree_string_map(self) -> Result<BTreeMap<String, Value>, Error> {
651 Self::map_into_btree_string_map(self.into_map()?)
652 }
653
654 pub fn to_btree_ref_string_map(&self) -> Result<BTreeMap<String, &Value>, Error> {
672 Self::map_ref_into_btree_string_map(self.to_map_ref()?)
673 }
674
675 pub fn to_ref_string_map<'a, I: FromIterator<(String, &'a Value)>>(
695 &'a self,
696 ) -> Result<I, Error> {
697 Self::map_ref_into_string_map(self.to_map_ref()?)
698 }
699
700 pub fn to_ref_string_map_mut<'a, I: FromIterator<(String, &'a mut Value)>>(
720 &'a mut self,
721 ) -> Result<I, Error> {
722 Self::map_mut_ref_into_string_map(self.as_map_mut_ref()?)
723 }
724
725 pub fn map_into_btree_string_map(map: ValueMap) -> Result<BTreeMap<String, Value>, Error> {
729 map.into_iter()
730 .map(|(key, value)| {
731 let key = key
732 .into_text()
733 .map_err(|_| Error::StructureError("expected key to be string".to_string()))?;
734 Ok((key, value))
735 })
736 .collect::<Result<BTreeMap<String, Value>, Error>>()
737 }
738
739 pub fn map_ref_into_btree_string_map(
743 map: &ValueMap,
744 ) -> Result<BTreeMap<String, &Value>, Error> {
745 map.iter()
746 .map(|(key, value)| {
747 let key = key
748 .to_text()
749 .map_err(|_| Error::StructureError("expected key to be string".to_string()))?;
750 Ok((key, value))
751 })
752 .collect::<Result<BTreeMap<String, &Value>, Error>>()
753 }
754
755 pub fn map_ref_into_indexed_string_map<'a, T>(
762 map: &'a ValueMap,
763 sort_key: &str,
764 ) -> Result<IndexMap<String, &'a Value>, Error>
765 where
766 T: TryFrom<i128>
767 + TryFrom<u128>
768 + TryFrom<u64>
769 + TryFrom<i64>
770 + TryFrom<u32>
771 + TryFrom<i32>
772 + TryFrom<u16>
773 + TryFrom<i16>
774 + TryFrom<u8>
775 + TryFrom<i8>
776 + Ord,
777 {
778 for (_, value) in map.iter() {
780 value.get_integer::<T>(sort_key)?;
781 }
782
783 let mut sorted_map: Vec<_> = map.iter().collect();
784
785 sorted_map.sort_by(|(_, value_1), (_, value_2)| {
786 let pos_1: T = value_1.get_integer(sort_key).expect("expected sort key");
787 let pos_2: T = value_2.get_integer(sort_key).expect("expected sort key");
788 pos_1.cmp(&pos_2)
789 });
790
791 sorted_map
792 .into_iter()
793 .map(|(key, value)| {
794 let key = key
795 .to_text()
796 .map_err(|_| Error::StructureError("expected key to be string".to_string()))?;
797 Ok((key, value))
798 })
799 .collect::<Result<IndexMap<String, &Value>, Error>>()
800 }
801
802 pub fn map_ref_into_string_map<'a, I: FromIterator<(String, &'a Value)>>(
806 map: &'a ValueMap,
807 ) -> Result<I, Error> {
808 map.iter()
809 .map(|(key, value)| {
810 let key = key
811 .to_text()
812 .map_err(|_| Error::StructureError("expected key to be string".to_string()))?;
813 Ok((key, value))
814 })
815 .collect::<Result<I, Error>>()
816 }
817
818 pub fn map_mut_ref_into_string_map<'a, I: FromIterator<(String, &'a mut Value)>>(
822 map: &'a mut ValueMap,
823 ) -> Result<I, Error> {
824 map.iter_mut()
825 .map(|(key, value)| {
826 let key = key
827 .to_text()
828 .map_err(|_| Error::StructureError("expected key to be string".to_string()))?;
829 Ok((key, value))
830 })
831 .collect::<Result<I, Error>>()
832 }
833}