Skip to main content

yaml_spanned/
mapping.rs

1use crate::spanned::Spanned;
2use crate::value::Value;
3use indexmap::IndexMap;
4use std::cmp::Ordering;
5
6struct Key<'a>(&'a Spanned<Value>);
7impl std::fmt::Debug for Key<'_> {
8    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
9        match self.0.as_ref() {
10            Value::Null => write!(f, "NULL"),
11            Value::Bool(boolean) => write!(f, "{boolean}"),
12            Value::String(value) => write!(f, "{value:?}"),
13            Value::Number(number) => write!(f, "{number}"),
14            Value::Sequence(sequence) => f.debug_list().entries(sequence).finish(),
15            Value::Mapping(mapping) => std::fmt::Display::fmt(mapping, f),
16            Value::Tagged(tagged) => std::fmt::Display::fmt(tagged, f),
17        }
18    }
19}
20
21#[derive(Debug, Clone, Default, Eq, PartialEq)]
22pub struct Mapping(pub IndexMap<Spanned<Value>, Spanned<Value>>);
23
24impl std::fmt::Display for Mapping {
25    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
26        f.debug_map()
27            .entries(self.0.iter().map(|(k, v)| (Key(k), crate::fmt::Display(v))))
28            .finish()
29    }
30}
31
32pub struct StringValueRepr<'a>(&'a Mapping);
33
34impl std::fmt::Debug for StringValueRepr<'_> {
35    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
36        std::fmt::Display::fmt(&self, f)
37    }
38}
39
40impl std::fmt::Display for StringValueRepr<'_> {
41    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
42        f.debug_map()
43            .entries(self.0.iter().map(|(k, v)| (Key(k), v.string_value_repr())))
44            .finish()
45    }
46}
47
48impl Mapping {
49    #[must_use]
50    pub fn string_value_repr(&self) -> StringValueRepr<'_> {
51        StringValueRepr(self)
52    }
53
54    // pub fn string_value(&self) -> String {
55    //     StringValueRepr(self).to_string()
56    // }
57}
58
59impl AsMut<IndexMap<Spanned<Value>, Spanned<Value>>> for Mapping {
60    fn as_mut(&mut self) -> &mut IndexMap<Spanned<Value>, Spanned<Value>> {
61        &mut self.0
62    }
63}
64
65impl AsRef<IndexMap<Spanned<Value>, Spanned<Value>>> for Mapping {
66    fn as_ref(&self) -> &IndexMap<Spanned<Value>, Spanned<Value>> {
67        &self.0
68    }
69}
70
71impl Mapping {
72    /// Creates an empty YAML map.
73    #[inline]
74    #[must_use]
75    pub fn new() -> Self {
76        Self::default()
77    }
78
79    /// Creates an empty YAML map with the given initial capacity.
80    #[inline]
81    #[must_use]
82    pub fn with_capacity(capacity: usize) -> Self {
83        Self(IndexMap::with_capacity(capacity))
84    }
85
86    /// Reserves capacity for at least `additional` more elements to be inserted
87    /// into the map. The map may reserve more space to avoid frequent
88    /// allocations.
89    ///
90    /// # Panics
91    ///
92    /// Panics if the new allocation size overflows `usize`.
93    #[inline]
94    pub fn reserve(&mut self, additional: usize) {
95        self.0.reserve(additional);
96    }
97
98    /// Shrinks the capacity of the map as much as possible. It will drop down
99    /// as much as possible while maintaining the internal rules and possibly
100    /// leaving some space in accordance with the resize policy.
101    #[inline]
102    pub fn shrink_to_fit(&mut self) {
103        self.0.shrink_to_fit();
104    }
105
106    /// Inserts a key-value pair into the map. If the key already existed, the
107    /// old value is returned.
108    #[inline]
109    pub fn insert(&mut self, k: Spanned<Value>, v: Spanned<Value>) -> Option<Spanned<Value>> {
110        self.0.insert(k, v)
111    }
112
113    /// Checks if the map contains the given key.
114    #[inline]
115    pub fn contains_key<I: Index>(&self, index: I) -> bool {
116        index.is_key_into(self)
117    }
118
119    /// Returns the value corresponding to the key in the map.
120    #[inline]
121    pub fn get<I: Index>(&self, index: I) -> Option<&Spanned<Value>> {
122        index.index_into(self)
123    }
124
125    /// Returns the mutable reference corresponding to the key in the map.
126    #[inline]
127    pub fn get_mut<I: Index>(&mut self, index: I) -> Option<&mut Spanned<Value>> {
128        index.index_into_mut(self)
129    }
130
131    /// Gets the given key's corresponding entry in the map for insertion and/or
132    /// in-place manipulation.
133    #[inline]
134    pub fn entry(&mut self, k: Spanned<Value>) -> Entry<'_> {
135        match self.0.entry(k) {
136            indexmap::map::Entry::Occupied(occupied) => Entry::Occupied(OccupiedEntry { occupied }),
137            indexmap::map::Entry::Vacant(vacant) => Entry::Vacant(VacantEntry { vacant }),
138        }
139    }
140
141    /// Removes and returns the value corresponding to the key from the map.
142    ///
143    /// This is equivalent to [`.swap_remove(index)`][Self::swap_remove],
144    /// replacing this entry's position with the last element. If you need to
145    /// preserve the relative order of the keys in the map, use
146    /// [`.shift_remove(key)`][Self::shift_remove] instead.
147    #[inline]
148    pub fn remove<I: Index>(&mut self, index: I) -> Option<Spanned<Value>> {
149        self.swap_remove(index)
150    }
151
152    /// Remove and return the key-value pair.
153    ///
154    /// This is equivalent to [`.swap_remove_entry(index)`][Self::swap_remove_entry],
155    /// replacing this entry's position with the last element. If you need to
156    /// preserve the relative order of the keys in the map, use
157    /// [`.shift_remove_entry(key)`][Self::shift_remove_entry] instead.
158    #[inline]
159    pub fn remove_entry<I: Index>(&mut self, index: I) -> Option<(Spanned<Value>, Spanned<Value>)> {
160        self.swap_remove_entry(index)
161    }
162
163    /// Removes and returns the value corresponding to the key from the map.
164    ///
165    /// Like [`Vec::swap_remove`], the entry is removed by swapping it with the
166    /// last element of the map and popping it off. This perturbs the position
167    /// of what used to be the last element!
168    #[inline]
169    pub fn swap_remove<I: Index>(&mut self, index: I) -> Option<Spanned<Value>> {
170        index.swap_remove_from(self)
171    }
172
173    /// Remove and return the key-value pair.
174    ///
175    /// Like [`Vec::swap_remove`], the entry is removed by swapping it with the
176    /// last element of the map and popping it off. This perturbs the position
177    /// of what used to be the last element!
178    #[inline]
179    pub fn swap_remove_entry<I: Index>(
180        &mut self,
181        index: I,
182    ) -> Option<(Spanned<Value>, Spanned<Value>)> {
183        index.swap_remove_entry_from(self)
184    }
185
186    /// Removes and returns the value corresponding to the key from the map.
187    ///
188    /// Like [`Vec::remove`], the entry is removed by shifting all of the
189    /// elements that follow it, preserving their relative order. This perturbs
190    /// the index of all of those elements!
191    #[inline]
192    pub fn shift_remove<I: Index>(&mut self, index: I) -> Option<Spanned<Value>> {
193        index.shift_remove_from(self)
194    }
195
196    /// Remove and return the key-value pair.
197    ///
198    /// Like [`Vec::remove`], the entry is removed by shifting all of the
199    /// elements that follow it, preserving their relative order. This perturbs
200    /// the index of all of those elements!
201    #[inline]
202    pub fn shift_remove_entry<I: Index>(
203        &mut self,
204        index: I,
205    ) -> Option<(Spanned<Value>, Spanned<Value>)> {
206        index.shift_remove_entry_from(self)
207    }
208
209    /// Scan through each key-value pair in the map and keep those where the
210    /// closure `keep` returns true.
211    #[inline]
212    pub fn retain<F>(&mut self, keep: F)
213    where
214        F: FnMut(&Spanned<Value>, &mut Spanned<Value>) -> bool,
215    {
216        self.0.retain(keep);
217    }
218
219    /// Returns the maximum number of key-value pairs the map can hold without
220    /// reallocating.
221    #[inline]
222    #[must_use]
223    pub fn capacity(&self) -> usize {
224        self.0.capacity()
225    }
226
227    /// Returns the number of key-value pairs in the map.
228    #[inline]
229    #[must_use]
230    pub fn len(&self) -> usize {
231        self.0.len()
232    }
233
234    /// Returns whether the map is currently empty.
235    #[inline]
236    #[must_use]
237    pub fn is_empty(&self) -> bool {
238        self.0.is_empty()
239    }
240
241    /// Clears the map of all key-value pairs.
242    #[inline]
243    pub fn clear(&mut self) {
244        self.0.clear();
245    }
246
247    /// Returns a double-ended iterator visiting all key-value pairs in order of
248    /// insertion. Iterator element type is `(&'a Value, &'a Value)`.
249    #[inline]
250    #[must_use]
251    pub fn iter(&self) -> Iter<'_> {
252        Iter {
253            iter: self.0.iter(),
254        }
255    }
256
257    /// Returns a double-ended iterator visiting all key-value pairs in order of
258    /// insertion. Iterator element type is `(&'a Value, &'a mut Value)`.
259    #[inline]
260    pub fn iter_mut(&mut self) -> IterMut<'_> {
261        IterMut {
262            iter: self.0.iter_mut(),
263        }
264    }
265
266    /// Return an iterator over the keys of the map.
267    #[must_use]
268    pub fn keys(&self) -> Keys<'_> {
269        Keys {
270            iter: self.0.keys(),
271        }
272    }
273
274    /// Return an owning iterator over the keys of the map.
275    #[must_use]
276    pub fn into_keys(self) -> IntoKeys {
277        IntoKeys {
278            iter: self.0.into_keys(),
279        }
280    }
281
282    /// Return an iterator over the values of the map.
283    #[must_use]
284    pub fn values(&self) -> Values<'_> {
285        Values {
286            iter: self.0.values(),
287        }
288    }
289
290    /// Return an iterator over mutable references to the values of the map.
291    pub fn values_mut(&mut self) -> ValuesMut<'_> {
292        ValuesMut {
293            iter: self.0.values_mut(),
294        }
295    }
296
297    /// Return an owning iterator over the values of the map.
298    #[must_use]
299    pub fn into_values(self) -> IntoValues {
300        IntoValues {
301            iter: self.0.into_values(),
302        }
303    }
304}
305
306/// A type that can be used to index into a `yaml_spanned::Mapping`. See the
307/// methods `get`, `get_mut`, `contains_key`, and `remove` of `Value`.
308///
309/// This trait is sealed and cannot be implemented for types outside of `yaml_spanned`.
310pub trait Index: crate::private::Sealed {
311    #[doc(hidden)]
312    fn is_key_into(&self, v: &Mapping) -> bool;
313
314    #[doc(hidden)]
315    fn index_into<'a>(&self, v: &'a Mapping) -> Option<&'a Spanned<Value>>;
316
317    #[doc(hidden)]
318    fn index_into_mut<'a>(&self, v: &'a mut Mapping) -> Option<&'a mut Spanned<Value>>;
319
320    #[doc(hidden)]
321    fn swap_remove_from(&self, v: &mut Mapping) -> Option<Spanned<Value>>;
322
323    #[doc(hidden)]
324    fn swap_remove_entry_from(&self, v: &mut Mapping) -> Option<(Spanned<Value>, Spanned<Value>)>;
325
326    #[doc(hidden)]
327    fn shift_remove_from(&self, v: &mut Mapping) -> Option<Spanned<Value>>;
328
329    #[doc(hidden)]
330    fn shift_remove_entry_from(&self, v: &mut Mapping) -> Option<(Spanned<Value>, Spanned<Value>)>;
331}
332
333struct HashLikeValue<'a>(&'a str);
334
335impl indexmap::Equivalent<Spanned<Value>> for HashLikeValue<'_> {
336    fn equivalent(&self, key: &Spanned<Value>) -> bool {
337        match key.as_ref() {
338            Value::String(string) => self.0 == string,
339            _ => false,
340        }
341    }
342}
343
344impl indexmap::Equivalent<Value> for HashLikeValue<'_> {
345    fn equivalent(&self, key: &Value) -> bool {
346        match key {
347            Value::String(string) => self.0 == string,
348            _ => false,
349        }
350    }
351}
352
353// NOTE: This impl must be consistent with Value's Hash impl.
354impl std::hash::Hash for HashLikeValue<'_> {
355    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
356        const STRING: Value = Value::String(String::new());
357        std::mem::discriminant(&STRING).hash(state);
358        self.0.hash(state);
359    }
360}
361
362impl Index for Spanned<Value> {
363    fn is_key_into(&self, v: &Mapping) -> bool {
364        v.0.contains_key(self)
365    }
366    fn index_into<'a>(&self, v: &'a Mapping) -> Option<&'a Spanned<Value>> {
367        v.0.get(self)
368    }
369    fn index_into_mut<'a>(&self, v: &'a mut Mapping) -> Option<&'a mut Spanned<Value>> {
370        v.0.get_mut(self)
371    }
372    fn swap_remove_from(&self, v: &mut Mapping) -> Option<Spanned<Value>> {
373        v.0.swap_remove(self)
374    }
375    fn swap_remove_entry_from(&self, v: &mut Mapping) -> Option<(Spanned<Value>, Spanned<Value>)> {
376        v.0.swap_remove_entry(self)
377    }
378    fn shift_remove_from(&self, v: &mut Mapping) -> Option<Spanned<Value>> {
379        v.0.shift_remove(self)
380    }
381    fn shift_remove_entry_from(&self, v: &mut Mapping) -> Option<(Spanned<Value>, Spanned<Value>)> {
382        v.0.shift_remove_entry(self)
383    }
384}
385
386impl Index for Value {
387    fn is_key_into(&self, v: &Mapping) -> bool {
388        v.0.contains_key(self)
389    }
390    fn index_into<'a>(&self, v: &'a Mapping) -> Option<&'a Spanned<Value>> {
391        v.0.get(self)
392    }
393    fn index_into_mut<'a>(&self, v: &'a mut Mapping) -> Option<&'a mut Spanned<Value>> {
394        v.0.get_mut(self)
395    }
396    fn swap_remove_from(&self, v: &mut Mapping) -> Option<Spanned<Value>> {
397        v.0.swap_remove(self)
398    }
399    fn swap_remove_entry_from(&self, v: &mut Mapping) -> Option<(Spanned<Value>, Spanned<Value>)> {
400        v.0.swap_remove_entry(self)
401    }
402    fn shift_remove_from(&self, v: &mut Mapping) -> Option<Spanned<Value>> {
403        v.0.shift_remove(self)
404    }
405    fn shift_remove_entry_from(&self, v: &mut Mapping) -> Option<(Spanned<Value>, Spanned<Value>)> {
406        v.0.shift_remove_entry(self)
407    }
408}
409
410impl Index for str {
411    fn is_key_into(&self, v: &Mapping) -> bool {
412        v.0.contains_key(&HashLikeValue(self))
413    }
414    fn index_into<'a>(&self, v: &'a Mapping) -> Option<&'a Spanned<Value>> {
415        v.0.get(&HashLikeValue(self))
416    }
417    fn index_into_mut<'a>(&self, v: &'a mut Mapping) -> Option<&'a mut Spanned<Value>> {
418        v.0.get_mut(&HashLikeValue(self))
419    }
420    fn swap_remove_from(&self, v: &mut Mapping) -> Option<Spanned<Value>> {
421        v.0.swap_remove(&HashLikeValue(self))
422    }
423    fn swap_remove_entry_from(&self, v: &mut Mapping) -> Option<(Spanned<Value>, Spanned<Value>)> {
424        v.0.swap_remove_entry(&HashLikeValue(self))
425    }
426    fn shift_remove_from(&self, v: &mut Mapping) -> Option<Spanned<Value>> {
427        v.0.shift_remove(&HashLikeValue(self))
428    }
429    fn shift_remove_entry_from(&self, v: &mut Mapping) -> Option<(Spanned<Value>, Spanned<Value>)> {
430        v.0.shift_remove_entry(&HashLikeValue(self))
431    }
432}
433
434impl Index for String {
435    fn is_key_into(&self, v: &Mapping) -> bool {
436        self.as_str().is_key_into(v)
437    }
438    fn index_into<'a>(&self, v: &'a Mapping) -> Option<&'a Spanned<Value>> {
439        self.as_str().index_into(v)
440    }
441    fn index_into_mut<'a>(&self, v: &'a mut Mapping) -> Option<&'a mut Spanned<Value>> {
442        self.as_str().index_into_mut(v)
443    }
444    fn swap_remove_from(&self, v: &mut Mapping) -> Option<Spanned<Value>> {
445        self.as_str().swap_remove_from(v)
446    }
447    fn swap_remove_entry_from(&self, v: &mut Mapping) -> Option<(Spanned<Value>, Spanned<Value>)> {
448        self.as_str().swap_remove_entry_from(v)
449    }
450    fn shift_remove_from(&self, v: &mut Mapping) -> Option<Spanned<Value>> {
451        self.as_str().shift_remove_from(v)
452    }
453    fn shift_remove_entry_from(&self, v: &mut Mapping) -> Option<(Spanned<Value>, Spanned<Value>)> {
454        self.as_str().shift_remove_entry_from(v)
455    }
456}
457
458impl<T> Index for &T
459where
460    T: ?Sized + Index,
461{
462    fn is_key_into(&self, v: &Mapping) -> bool {
463        (**self).is_key_into(v)
464    }
465    fn index_into<'a>(&self, v: &'a Mapping) -> Option<&'a Spanned<Value>> {
466        (**self).index_into(v)
467    }
468    fn index_into_mut<'a>(&self, v: &'a mut Mapping) -> Option<&'a mut Spanned<Value>> {
469        (**self).index_into_mut(v)
470    }
471    fn swap_remove_from(&self, v: &mut Mapping) -> Option<Spanned<Value>> {
472        (**self).swap_remove_from(v)
473    }
474    fn swap_remove_entry_from(&self, v: &mut Mapping) -> Option<(Spanned<Value>, Spanned<Value>)> {
475        (**self).swap_remove_entry_from(v)
476    }
477    fn shift_remove_from(&self, v: &mut Mapping) -> Option<Spanned<Value>> {
478        (**self).shift_remove_from(v)
479    }
480    fn shift_remove_entry_from(&self, v: &mut Mapping) -> Option<(Spanned<Value>, Spanned<Value>)> {
481        (**self).shift_remove_entry_from(v)
482    }
483}
484
485#[allow(clippy::derived_hash_with_manual_eq)]
486impl std::hash::Hash for Mapping {
487    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
488        use std::hash::Hasher;
489        // Hash the kv pairs in a way that is not sensitive to their order.
490        let mut xor = 0;
491        for (k, v) in &self.0 {
492            let mut hasher = std::collections::hash_map::DefaultHasher::new();
493            k.hash(&mut hasher);
494            v.hash(&mut hasher);
495            xor ^= hasher.finish();
496        }
497        xor.hash(state);
498    }
499}
500
501impl PartialOrd for Mapping {
502    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
503        let mut self_entries = Vec::from_iter(self);
504        let mut other_entries = Vec::from_iter(other);
505
506        // Sort in an arbitrary order that is consistent with Value's PartialOrd
507        // impl.
508        fn total_cmp(a: &Value, b: &Value) -> Ordering {
509            match (a, b) {
510                (Value::Null, Value::Null) => Ordering::Equal,
511                (Value::Null, _) => Ordering::Less,
512                (_, Value::Null) => Ordering::Greater,
513
514                (Value::Bool(a), Value::Bool(b)) => a.cmp(b),
515                (Value::Bool(_), _) => Ordering::Less,
516                (_, Value::Bool(_)) => Ordering::Greater,
517
518                (Value::Number(a), Value::Number(b)) => a.total_cmp(b),
519                (Value::Number(_), _) => Ordering::Less,
520                (_, Value::Number(_)) => Ordering::Greater,
521
522                (Value::String(a), Value::String(b)) => a.cmp(b),
523                (Value::String(_), _) => Ordering::Less,
524                (_, Value::String(_)) => Ordering::Greater,
525
526                (Value::Sequence(a), Value::Sequence(b)) => {
527                    iter_cmp_by(a, b, |a, b| total_cmp(a.as_ref(), b.as_ref()))
528                }
529                (Value::Sequence(_), _) => Ordering::Less,
530                (_, Value::Sequence(_)) => Ordering::Greater,
531
532                (Value::Mapping(a), Value::Mapping(b)) => {
533                    iter_cmp_by(a, b, |(ak, av), (bk, bv)| {
534                        total_cmp(ak.as_ref(), bk.as_ref())
535                            .then_with(|| total_cmp(av.as_ref(), bv.as_ref()))
536                    })
537                }
538                (Value::Mapping(_), _) => Ordering::Less,
539                (_, Value::Mapping(_)) => Ordering::Greater,
540
541                (Value::Tagged(a), Value::Tagged(b)) => a
542                    .tag
543                    .cmp(&b.tag)
544                    .then_with(|| total_cmp(a.value.as_ref(), b.value.as_ref())),
545            }
546        }
547
548        fn iter_cmp_by<I, F>(this: I, other: I, mut cmp: F) -> Ordering
549        where
550            I: IntoIterator,
551            F: FnMut(I::Item, I::Item) -> Ordering,
552        {
553            let mut this = this.into_iter();
554            let mut other = other.into_iter();
555
556            loop {
557                let x = match this.next() {
558                    None => {
559                        if other.next().is_none() {
560                            return Ordering::Equal;
561                        }
562                        return Ordering::Less;
563                    }
564                    Some(val) => val,
565                };
566
567                let y = match other.next() {
568                    None => return Ordering::Greater,
569                    Some(val) => val,
570                };
571
572                match cmp(x, y) {
573                    Ordering::Equal => {}
574                    non_eq => return non_eq,
575                }
576            }
577        }
578
579        // While sorting by map key, we get to assume that no two keys are
580        // equal, otherwise they wouldn't both be in the map. This is not a safe
581        // assumption outside of this situation.
582        let total_cmp = |&(a, _): &(&Spanned<Value>, &Spanned<Value>),
583                         &(b, _): &(&Spanned<Value>, &Spanned<Value>)| {
584            total_cmp(a.as_ref(), b.as_ref())
585        };
586        self_entries.sort_by(total_cmp);
587        other_entries.sort_by(total_cmp);
588        self_entries.partial_cmp(&other_entries)
589    }
590}
591
592impl<I> std::ops::Index<I> for Mapping
593where
594    I: Index,
595{
596    type Output = Spanned<Value>;
597
598    #[inline]
599    #[track_caller]
600    fn index(&self, index: I) -> &Self::Output {
601        index.index_into(self).unwrap()
602    }
603}
604
605impl<I> std::ops::IndexMut<I> for Mapping
606where
607    I: Index,
608{
609    #[inline]
610    #[track_caller]
611    fn index_mut(&mut self, index: I) -> &mut Spanned<Value> {
612        index.index_into_mut(self).unwrap()
613    }
614}
615
616impl Extend<(Spanned<Value>, Spanned<Value>)> for Mapping {
617    #[inline]
618    fn extend<I: IntoIterator<Item = (Spanned<Value>, Spanned<Value>)>>(&mut self, iter: I) {
619        self.0.extend(iter);
620    }
621}
622
623impl FromIterator<(Spanned<Value>, Spanned<Value>)> for Mapping {
624    #[inline]
625    fn from_iter<I: IntoIterator<Item = (Spanned<Value>, Spanned<Value>)>>(iter: I) -> Self {
626        Mapping(IndexMap::from_iter(iter))
627    }
628}
629
630macro_rules! delegate_iterator {
631    (($name:ident $($generics:tt)*) => $item:ty) => {
632        impl $($generics)* Iterator for $name $($generics)* {
633            type Item = $item;
634            #[inline]
635            fn next(&mut self) -> Option<Self::Item> {
636                self.iter.next()
637            }
638            #[inline]
639            fn size_hint(&self) -> (usize, Option<usize>) {
640                self.iter.size_hint()
641            }
642        }
643
644        impl $($generics)* ExactSizeIterator for $name $($generics)* {
645            #[inline]
646            fn len(&self) -> usize {
647                self.iter.len()
648            }
649        }
650    }
651}
652
653/// Iterator over `&yaml_spanned::Mapping`.
654pub struct Iter<'a> {
655    iter: indexmap::map::Iter<'a, Spanned<Value>, Spanned<Value>>,
656}
657
658delegate_iterator!((Iter<'a>) => (&'a Spanned<Value>, &'a Spanned<Value>));
659
660impl<'a> IntoIterator for &'a Mapping {
661    type Item = (&'a Spanned<Value>, &'a Spanned<Value>);
662    type IntoIter = Iter<'a>;
663    #[inline]
664    fn into_iter(self) -> Self::IntoIter {
665        Iter {
666            iter: self.0.iter(),
667        }
668    }
669}
670
671/// Iterator over `&mut yaml_spanned::Mapping`.
672pub struct IterMut<'a> {
673    iter: indexmap::map::IterMut<'a, Spanned<Value>, Spanned<Value>>,
674}
675
676delegate_iterator!((IterMut<'a>) => (&'a Spanned<Value>, &'a mut Spanned<Value>));
677
678impl<'a> IntoIterator for &'a mut Mapping {
679    type Item = (&'a Spanned<Value>, &'a mut Spanned<Value>);
680    type IntoIter = IterMut<'a>;
681    #[inline]
682    fn into_iter(self) -> Self::IntoIter {
683        IterMut {
684            iter: self.0.iter_mut(),
685        }
686    }
687}
688
689/// Iterator over `yaml_spanned::Mapping` by value.
690pub struct IntoIter {
691    iter: indexmap::map::IntoIter<Spanned<Value>, Spanned<Value>>,
692}
693
694delegate_iterator!((IntoIter) => (Spanned<Value>, Spanned<Value>));
695
696impl IntoIterator for Mapping {
697    type Item = (Spanned<Value>, Spanned<Value>);
698    type IntoIter = IntoIter;
699    #[inline]
700    fn into_iter(self) -> Self::IntoIter {
701        IntoIter {
702            iter: self.0.into_iter(),
703        }
704    }
705}
706
707/// Iterator of the keys of a `&yaml_spanned::Mapping`.
708pub struct Keys<'a> {
709    iter: indexmap::map::Keys<'a, Spanned<Value>, Spanned<Value>>,
710}
711
712delegate_iterator!((Keys<'a>) => &'a Spanned<Value>);
713
714/// Iterator of the keys of a `yaml_spanned::Mapping`.
715pub struct IntoKeys {
716    iter: indexmap::map::IntoKeys<Spanned<Value>, Spanned<Value>>,
717}
718
719delegate_iterator!((IntoKeys) => Spanned<Value>);
720
721/// Iterator of the values of a `&yaml_spanned::Mapping`.
722pub struct Values<'a> {
723    iter: indexmap::map::Values<'a, Spanned<Value>, Spanned<Value>>,
724}
725
726delegate_iterator!((Values<'a>) => &'a Spanned<Value>);
727
728/// Iterator of the values of a `&mut yaml_spanned::Mapping`.
729pub struct ValuesMut<'a> {
730    iter: indexmap::map::ValuesMut<'a, Spanned<Value>, Spanned<Value>>,
731}
732
733delegate_iterator!((ValuesMut<'a>) => &'a mut Spanned<Value>);
734
735/// Iterator of the values of a `yaml_spanned::Mapping`.
736pub struct IntoValues {
737    iter: indexmap::map::IntoValues<Spanned<Value>, Spanned<Value>>,
738}
739
740delegate_iterator!((IntoValues) => Spanned<Value>);
741
742/// Entry for an existing key-value pair or a vacant location to insert one.
743pub enum Entry<'a> {
744    /// Existing slot with equivalent key.
745    Occupied(OccupiedEntry<'a>),
746    /// Vacant slot (no equivalent key in the map).
747    Vacant(VacantEntry<'a>),
748}
749
750/// A view into an occupied entry in a [`Mapping`]. It is part of the [`Entry`]
751/// enum.
752pub struct OccupiedEntry<'a> {
753    occupied: indexmap::map::OccupiedEntry<'a, Spanned<Value>, Spanned<Value>>,
754}
755
756/// A view into a vacant entry in a [`Mapping`]. It is part of the [`Entry`]
757/// enum.
758pub struct VacantEntry<'a> {
759    vacant: indexmap::map::VacantEntry<'a, Spanned<Value>, Spanned<Value>>,
760}
761
762impl<'a> Entry<'a> {
763    /// Returns a reference to this entry's key.
764    #[must_use]
765    pub fn key(&self) -> &Spanned<Value> {
766        match self {
767            Entry::Vacant(e) => e.key(),
768            Entry::Occupied(e) => e.key(),
769        }
770    }
771
772    /// Ensures a value is in the entry by inserting the default if empty, and
773    /// returns a mutable reference to the value in the entry.
774    #[must_use]
775    pub fn or_insert(self, default: Spanned<Value>) -> &'a mut Spanned<Value> {
776        match self {
777            Entry::Vacant(entry) => entry.insert(default),
778            Entry::Occupied(entry) => entry.into_mut(),
779        }
780    }
781
782    /// Ensures a value is in the entry by inserting the result of the default
783    /// function if empty, and returns a mutable reference to the value in the
784    /// entry.
785    pub fn or_insert_with<F>(self, default: F) -> &'a mut Spanned<Value>
786    where
787        F: FnOnce() -> Spanned<Value>,
788    {
789        match self {
790            Entry::Vacant(entry) => entry.insert(default()),
791            Entry::Occupied(entry) => entry.into_mut(),
792        }
793    }
794
795    /// Provides in-place mutable access to an occupied entry before any
796    /// potential inserts into the map.
797    pub fn and_modify<F>(self, f: F) -> Self
798    where
799        F: FnOnce(&mut Spanned<Value>),
800    {
801        match self {
802            Entry::Occupied(mut entry) => {
803                f(entry.get_mut());
804                Entry::Occupied(entry)
805            }
806            Entry::Vacant(entry) => Entry::Vacant(entry),
807        }
808    }
809}
810
811impl<'a> OccupiedEntry<'a> {
812    /// Gets a reference to the key in the entry.
813    #[inline]
814    #[must_use]
815    pub fn key(&self) -> &Spanned<Value> {
816        self.occupied.key()
817    }
818
819    /// Gets a reference to the value in the entry.
820    #[inline]
821    #[must_use]
822    pub fn get(&self) -> &Spanned<Value> {
823        self.occupied.get()
824    }
825
826    /// Gets a mutable reference to the value in the entry.
827    #[inline]
828    pub fn get_mut(&mut self) -> &mut Spanned<Value> {
829        self.occupied.get_mut()
830    }
831
832    /// Converts the entry into a mutable reference to its value.
833    #[inline]
834    #[must_use]
835    pub fn into_mut(self) -> &'a mut Spanned<Value> {
836        self.occupied.into_mut()
837    }
838
839    /// Sets the value of the entry with the `OccupiedEntry`'s key, and returns
840    /// the entry's old value.
841    #[inline]
842    pub fn insert(&mut self, value: Spanned<Value>) -> Spanned<Value> {
843        self.occupied.insert(value)
844    }
845
846    /// Takes the value of the entry out of the map, and returns it.
847    #[inline]
848    #[must_use]
849    pub fn remove(self) -> Spanned<Value> {
850        self.occupied.swap_remove()
851    }
852
853    /// Remove and return the key, value pair stored in the map for this entry.
854    #[inline]
855    #[must_use]
856    pub fn remove_entry(self) -> (Spanned<Value>, Spanned<Value>) {
857        self.occupied.swap_remove_entry()
858    }
859}
860
861impl<'a> VacantEntry<'a> {
862    /// Gets a reference to the key that would be used when inserting a value
863    /// through the `VacantEntry`.
864    #[inline]
865    #[must_use]
866    pub fn key(&self) -> &Spanned<Value> {
867        self.vacant.key()
868    }
869
870    /// Takes ownership of the key, leaving the entry vacant.
871    #[inline]
872    #[must_use]
873    pub fn into_key(self) -> Spanned<Value> {
874        self.vacant.into_key()
875    }
876
877    /// Sets the value of the entry with the `VacantEntry`'s key, and returns a
878    /// mutable reference to it.
879    #[inline]
880    #[must_use]
881    pub fn insert(self, value: Spanned<Value>) -> &'a mut Spanned<Value> {
882        self.vacant.insert(value)
883    }
884}
885
886#[cfg(feature = "serde")]
887impl serde::Serialize for Mapping {
888    #[inline]
889    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
890        use serde::ser::SerializeMap;
891        let mut map_serializer = serializer.serialize_map(Some(self.len()))?;
892        for (k, v) in self {
893            map_serializer.serialize_entry(k, v)?;
894        }
895        map_serializer.end()
896    }
897}
898
899#[cfg(feature = "serde")]
900impl<'de> serde::Deserialize<'de> for Mapping {
901    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
902    where
903        D: serde::Deserializer<'de>,
904    {
905        struct Visitor;
906
907        impl<'de> serde::de::Visitor<'de> for Visitor {
908            type Value = Mapping;
909
910            fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
911                formatter.write_str("a YAML mapping")
912            }
913
914            #[inline]
915            fn visit_unit<E>(self) -> Result<Self::Value, E>
916            where
917                E: serde::de::Error,
918            {
919                Ok(Mapping::new())
920            }
921
922            #[inline]
923            fn visit_map<A>(self, mut data: A) -> Result<Self::Value, A::Error>
924            where
925                A: serde::de::MapAccess<'de>,
926            {
927                let mut mapping = Mapping::new();
928
929                // while let Some(key) = data.next_key::<Value>()? {
930                while let Some(key) = data.next_key()? {
931                    // match mapping.entry(Spanned::dummy(key)) {
932                    match mapping.entry(key) {
933                        Entry::Occupied(entry) => {
934                            return Err(serde::de::Error::custom(DuplicateKeyError { entry }));
935                        }
936                        Entry::Vacant(entry) => {
937                            // let value: Value = data.next_value()?;
938                            let value = data.next_value()?;
939                            // entry.insert(Spanned::dummy(value));
940                            _ = entry.insert(value);
941                        }
942                    }
943                }
944
945                Ok(mapping)
946            }
947        }
948
949        deserializer.deserialize_map(Visitor)
950    }
951}
952
953struct DuplicateKeyError<'a> {
954    entry: OccupiedEntry<'a>,
955}
956
957impl std::fmt::Display for DuplicateKeyError<'_> {
958    fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
959        formatter.write_str("duplicate entry ")?;
960        match self.entry.key().as_ref() {
961            Value::Null => formatter.write_str("with null key"),
962            Value::Bool(boolean) => write!(formatter, "with key `{boolean}`"),
963            Value::Number(number) => write!(formatter, "with key {number}"),
964            Value::String(string) => write!(formatter, "with key {string:?}"),
965            Value::Sequence(_) | Value::Mapping(_) | Value::Tagged(_) => {
966                formatter.write_str("in YAML map")
967            }
968        }
969    }
970}
971
972// #[allow(clippy::derived_hash_with_manual_eq)]
973// impl std::hash::Hash for Mapping {
974//     fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
975//         use std::collections::hash_map::DefaultHasher;
976//         use std::hash::Hasher;
977//         // Hash the kv pairs in a way that is not sensitive to their order.
978//         let mut xor = 0;
979//         for (k, v) in self.0.iter() {
980//             let mut hasher = DefaultHasher::new();
981//             k.hash(&mut hasher);
982//             v.hash(&mut hasher);
983//             xor ^= hasher.finish();
984//         }
985//         xor.hash(state);
986//     }
987// }
988
989#[cfg(test)]
990mod tests {
991    use crate::{Mapping, Value};
992    use color_eyre::eyre;
993    use indoc::indoc;
994
995    #[test]
996    fn test_mapping() -> eyre::Result<()> {
997        crate::tests::init();
998
999        let yaml = indoc! {"
1000            substructure:
1001              a: 'foo'
1002              b: 'bar'
1003        "};
1004
1005        let value = crate::from_str(yaml)?;
1006        similar_asserts::assert_eq!(
1007            value.clone().cleared_spans().into_inner(),
1008            Value::from(Mapping::from_iter([(
1009                "substructure".into(),
1010                Mapping::from_iter([("a".into(), "foo".into()), ("b".into(), "bar".into()),])
1011                    .into()
1012            ),]))
1013        );
1014
1015        #[cfg(feature = "serde")]
1016        {
1017            #[derive(Debug, serde::Deserialize, PartialEq)]
1018            struct Data {
1019                pub substructure: serde_yaml::Mapping,
1020            }
1021
1022            let mut expected = Data {
1023                substructure: serde_yaml::Mapping::new(),
1024            };
1025            expected.substructure.insert(
1026                serde_yaml::Value::String("a".to_owned()),
1027                serde_yaml::Value::String("foo".to_owned()),
1028            );
1029            expected.substructure.insert(
1030                serde_yaml::Value::String("b".to_owned()),
1031                serde_yaml::Value::String("bar".to_owned()),
1032            );
1033
1034            similar_asserts::assert_eq!(crate::from_value::<Data>(&value)?, expected);
1035        }
1036
1037        Ok(())
1038    }
1039}