Skip to main content

dbt_yaml/
mapping.rs

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