creator_plist/
dictionary.rs

1//! A map of String to plist::Value.
2//!
3//! The map is currently backed by an [`IndexMap`]. This may be changed in a future minor release.
4//!
5//! [`IndexMap`]: https://docs.rs/indexmap/latest/indexmap/map/struct.IndexMap.html
6
7//use serde::{de, ser};
8use indexmap::{map, IndexMap};
9use std::{
10    fmt::{self, Debug},
11    iter::FromIterator,
12    ops,
13};
14
15use crate::Value;
16
17/// Represents a plist dictionary type.
18pub struct Dictionary {
19    map: IndexMap<String, Value>,
20}
21
22impl Dictionary {
23    /// Makes a new empty `Dictionary`.
24    #[inline]
25    pub fn new() -> Self {
26        Dictionary {
27            map: IndexMap::new(),
28        }
29    }
30
31    /// Clears the dictionary, removing all values.
32    #[inline]
33    pub fn clear(&mut self) {
34        self.map.clear()
35    }
36
37    /// Returns a reference to the value corresponding to the key.
38    #[inline]
39    pub fn get(&self, key: &str) -> Option<&Value> {
40        self.map.get(key)
41    }
42
43    /// Returns true if the dictionary contains a value for the specified key.
44    #[inline]
45    pub fn contains_key(&self, key: &str) -> bool {
46        self.map.contains_key(key)
47    }
48
49    /// Returns a mutable reference to the value corresponding to the key.
50    #[inline]
51    pub fn get_mut(&mut self, key: &str) -> Option<&mut Value> {
52        self.map.get_mut(key)
53    }
54
55    /// Inserts a key-value pair into the dictionary.
56    ///
57    /// If the dictionary did not have this key present, `None` is returned.
58    ///
59    /// If the dictionary did have this key present, the value is updated, and the old value is
60    /// returned.
61    #[inline]
62    pub fn insert(&mut self, k: String, v: Value) -> Option<Value> {
63        self.map.insert(k, v)
64    }
65
66    /// Removes a key from the dictionary, returning the value at the key if the key was previously
67    /// in the dictionary.
68    #[inline]
69    pub fn remove(&mut self, key: &str) -> Option<Value> {
70        self.map.remove(key)
71    }
72
73    /// Gets the given key's corresponding entry in the dictionary for in-place manipulation.
74    // Entry functionality is unstable until I can figure out how to use either Cow<str> or
75    // T: AsRef<str> + Into<String>
76    #[cfg(any(
77        test,
78        feature = "enable_unstable_features_that_may_break_with_minor_version_bumps"
79    ))]
80    pub fn entry<S>(&mut self, key: S) -> Entry
81    where
82        S: Into<String>,
83    {
84        match self.map.entry(key.into()) {
85            map::Entry::Vacant(vacant) => Entry::Vacant(VacantEntry { vacant }),
86            map::Entry::Occupied(occupied) => Entry::Occupied(OccupiedEntry { occupied }),
87        }
88    }
89
90    /// Returns the number of elements in the dictionary.
91    #[inline]
92    pub fn len(&self) -> usize {
93        self.map.len()
94    }
95
96    /// Returns true if the dictionary contains no elements.
97    #[inline]
98    pub fn is_empty(&self) -> bool {
99        self.map.is_empty()
100    }
101
102    /// Gets an iterator over the entries of the dictionary.
103    #[inline]
104    pub fn iter(&self) -> Iter {
105        Iter {
106            iter: self.map.iter(),
107        }
108    }
109
110    /// Gets a mutable iterator over the entries of the dictionary.
111    #[inline]
112    pub fn iter_mut(&mut self) -> IterMut {
113        IterMut {
114            iter: self.map.iter_mut(),
115        }
116    }
117
118    /// Gets an iterator over the keys of the dictionary.
119    #[inline]
120    pub fn keys(&self) -> Keys {
121        Keys {
122            iter: self.map.keys(),
123        }
124    }
125
126    /// Gets an iterator over the values of the dictionary.
127    #[inline]
128    pub fn values(&self) -> Values {
129        Values {
130            iter: self.map.values(),
131        }
132    }
133
134    /// Gets an iterator over mutable values of the dictionary.
135    #[inline]
136    pub fn values_mut(&mut self) -> ValuesMut {
137        ValuesMut {
138            iter: self.map.values_mut(),
139        }
140    }
141}
142
143impl Default for Dictionary {
144    #[inline]
145    fn default() -> Self {
146        Dictionary {
147            map: Default::default(),
148        }
149    }
150}
151
152impl Clone for Dictionary {
153    #[inline]
154    fn clone(&self) -> Self {
155        Dictionary {
156            map: self.map.clone(),
157        }
158    }
159}
160
161impl PartialEq for Dictionary {
162    #[inline]
163    fn eq(&self, other: &Self) -> bool {
164        self.map.eq(&other.map)
165    }
166}
167
168/// Access an element of this dictionary. Panics if the given key is not present in the dictionary.
169///
170/// ```
171/// # use plist::Value;
172/// #
173/// # let val = &Value::String("".to_owned());
174/// # let _ =
175/// match *val {
176///     Value::Array(ref arr) => arr[0].as_string(),
177///     Value::Dictionary(ref dict) => dict["type"].as_string(),
178///     Value::String(ref s) => Some(s.as_str()),
179///     _ => None,
180/// }
181/// # ;
182/// ```
183impl<'a> ops::Index<&'a str> for Dictionary {
184    type Output = Value;
185
186    fn index(&self, index: &str) -> &Value {
187        self.map.index(index)
188    }
189}
190
191/// Mutably access an element of this dictionary. Panics if the given key is not present in the
192/// dictionary.
193///
194/// ```
195/// # let mut dict = plist::Dictionary::new();
196/// # dict.insert("key".to_owned(), plist::Value::Boolean(false));
197/// #
198/// dict["key"] = "value".into();
199/// ```
200impl<'a> ops::IndexMut<&'a str> for Dictionary {
201    fn index_mut(&mut self, index: &str) -> &mut Value {
202        self.map.get_mut(index).expect("no entry found for key")
203    }
204}
205
206impl Debug for Dictionary {
207    #[inline]
208    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
209        self.map.fmt(formatter)
210    }
211}
212
213/*impl ser::Serialize for Dictionary {
214    #[inline]
215    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
216    where
217        S: ser::Serializer,
218    {
219        use serde::ser::SerializeMap;
220        let mut map = try!(serializer.serialize_map(Some(self.len())));
221        for (k, v) in self {
222            try!(map.serialize_key(k));
223            try!(map.serialize_value(v));
224        }
225        map.end()
226    }
227}
228
229impl<'de> de::Deserialize<'de> for Dictionary {
230    #[inline]
231    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
232    where
233        D: de::Deserializer<'de>,
234    {
235        struct Visitor;
236
237        impl<'de> de::Visitor<'de> for Visitor {
238            type Value = Dictionary;
239
240            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
241                formatter.write_str("a map")
242            }
243
244            #[inline]
245            fn visit_unit<E>(self) -> Result<Self::Value, E>
246            where
247                E: de::Error,
248            {
249                Ok(Dictionary::new())
250            }
251
252            #[inline]
253            fn visit_map<V>(self, mut visitor: V) -> Result<Self::Value, V::Error>
254            where
255                V: de::MapAccess<'de>,
256            {
257                let mut values = Dictionary::new();
258
259                while let Some((key, value)) = try!(visitor.next_entry()) {
260                    values.insert(key, value);
261                }
262
263                Ok(values)
264            }
265        }
266
267        deserializer.deserialize_map(Visitor)
268    }
269}*/
270
271impl FromIterator<(String, Value)> for Dictionary {
272    fn from_iter<T>(iter: T) -> Self
273    where
274        T: IntoIterator<Item = (String, Value)>,
275    {
276        Dictionary {
277            map: FromIterator::from_iter(iter),
278        }
279    }
280}
281
282impl Extend<(String, Value)> for Dictionary {
283    fn extend<T>(&mut self, iter: T)
284    where
285        T: IntoIterator<Item = (String, Value)>,
286    {
287        self.map.extend(iter);
288    }
289}
290
291macro_rules! delegate_iterator {
292    (($name:ident $($generics:tt)*) => $item:ty) => {
293        impl $($generics)* Iterator for $name $($generics)* {
294            type Item = $item;
295            #[inline]
296            fn next(&mut self) -> Option<Self::Item> {
297                self.iter.next()
298            }
299            #[inline]
300            fn size_hint(&self) -> (usize, Option<usize>) {
301                self.iter.size_hint()
302            }
303        }
304
305        /*impl $($generics)* DoubleEndedIterator for $name $($generics)* {
306            #[inline]
307            fn next_back(&mut self) -> Option<Self::Item> {
308                self.iter.next_back()
309            }
310        }*/
311
312        impl $($generics)* ExactSizeIterator for $name $($generics)* {
313            #[inline]
314            fn len(&self) -> usize {
315                self.iter.len()
316            }
317        }
318    }
319}
320
321//////////////////////////////////////////////////////////////////////////////
322
323/// A view into a single entry in a dictionary, which may either be vacant or occupied.
324/// This enum is constructed from the [`entry`] method on [`Dictionary`].
325///
326/// [`entry`]: struct.Dictionary.html#method.entry
327/// [`Dictionary`]: struct.Dictionary.html
328#[cfg(any(
329    test,
330    feature = "enable_unstable_features_that_may_break_with_minor_version_bumps"
331))]
332pub enum Entry<'a> {
333    /// A vacant Entry.
334    Vacant(VacantEntry<'a>),
335    /// An occupied Entry.
336    Occupied(OccupiedEntry<'a>),
337}
338
339/// A vacant Entry. It is part of the [`Entry`] enum.
340///
341/// [`Entry`]: enum.Entry.html
342#[cfg(any(
343    test,
344    feature = "enable_unstable_features_that_may_break_with_minor_version_bumps"
345))]
346pub struct VacantEntry<'a> {
347    vacant: map::VacantEntry<'a, String, Value>,
348}
349
350/// An occupied Entry. It is part of the [`Entry`] enum.
351///
352/// [`Entry`]: enum.Entry.html
353#[cfg(any(
354    test,
355    feature = "enable_unstable_features_that_may_break_with_minor_version_bumps"
356))]
357pub struct OccupiedEntry<'a> {
358    occupied: map::OccupiedEntry<'a, String, Value>,
359}
360
361#[cfg(any(
362    test,
363    feature = "enable_unstable_features_that_may_break_with_minor_version_bumps"
364))]
365impl<'a> Entry<'a> {
366    /// Returns a reference to this entry's key.
367    ///
368    /// # Examples
369    ///
370    /// ```
371    /// let mut dict = plist::Dictionary::new();
372    /// assert_eq!(dict.entry("serde").key(), &"serde");
373    /// ```
374    pub fn key(&self) -> &String {
375        match *self {
376            Entry::Vacant(ref e) => e.key(),
377            Entry::Occupied(ref e) => e.key(),
378        }
379    }
380
381    /// Ensures a value is in the entry by inserting the default if empty, and returns a mutable
382    /// reference to the value in the entry.
383    ///
384    /// # Examples
385    ///
386    /// ```
387    /// let mut dict = plist::Dictionary::new();
388    /// dict.entry("serde").or_insert(12.into());
389    ///
390    /// assert_eq!(dict["serde"], 12.into());
391    /// ```
392    pub fn or_insert(self, default: Value) -> &'a mut Value {
393        match self {
394            Entry::Vacant(entry) => entry.insert(default),
395            Entry::Occupied(entry) => entry.into_mut(),
396        }
397    }
398
399    /// Ensures a value is in the entry by inserting the result of the default function if empty,
400    /// and returns a mutable reference to the value in the entry.
401    ///
402    /// # Examples
403    ///
404    /// ```
405    /// let mut dict = plist::Dictionary::new();
406    /// dict.entry("serde").or_insert_with(|| "hoho".into());
407    ///
408    /// assert_eq!(dict["serde"], "hoho".into());
409    /// ```
410    pub fn or_insert_with<F>(self, default: F) -> &'a mut Value
411    where
412        F: FnOnce() -> Value,
413    {
414        match self {
415            Entry::Vacant(entry) => entry.insert(default()),
416            Entry::Occupied(entry) => entry.into_mut(),
417        }
418    }
419}
420
421#[cfg(any(
422    test,
423    feature = "enable_unstable_features_that_may_break_with_minor_version_bumps"
424))]
425impl<'a> VacantEntry<'a> {
426    /// Gets a reference to the key that would be used when inserting a value through the
427    /// VacantEntry.
428    ///
429    /// # Examples
430    ///
431    /// ```
432    /// use plist::dictionary::Entry;
433    ///
434    /// let mut dict = plist::Dictionary::new();
435    ///
436    /// match dict.entry("serde") {
437    ///     Entry::Vacant(vacant) => assert_eq!(vacant.key(), &"serde"),
438    ///     Entry::Occupied(_) => unimplemented!(),
439    /// }
440    /// ```
441    #[inline]
442    pub fn key(&self) -> &String {
443        self.vacant.key()
444    }
445
446    /// Sets the value of the entry with the VacantEntry's key, and returns a mutable reference
447    /// to it.
448    ///
449    /// # Examples
450    ///
451    /// ```
452    /// use plist::dictionary::Entry;
453    ///
454    /// let mut dict = plist::Dictionary::new();
455    ///
456    /// match dict.entry("serde") {
457    ///     Entry::Vacant(vacant) => vacant.insert("hoho".into()),
458    ///     Entry::Occupied(_) => unimplemented!(),
459    /// };
460    /// ```
461    #[inline]
462    pub fn insert(self, value: Value) -> &'a mut Value {
463        self.vacant.insert(value)
464    }
465}
466
467#[cfg(any(
468    test,
469    feature = "enable_unstable_features_that_may_break_with_minor_version_bumps"
470))]
471impl<'a> OccupiedEntry<'a> {
472    /// Gets a reference to the key in the entry.
473    ///
474    /// # Examples
475    ///
476    /// ```
477    /// use plist::dictionary::Entry;
478    ///
479    /// let mut dict = plist::Dictionary::new();
480    /// dict.insert("serde".to_owned(), 12.into());
481    ///
482    /// match dict.entry("serde") {
483    ///     Entry::Occupied(occupied) => assert_eq!(occupied.key(), &"serde"),
484    ///     Entry::Vacant(_) => unimplemented!(),
485    /// }
486    /// ```
487    #[inline]
488    pub fn key(&self) -> &String {
489        self.occupied.key()
490    }
491
492    /// Gets a reference to the value in the entry.
493    ///
494    /// # Examples
495    ///
496    /// ```
497    /// use plist::Value;
498    /// use plist::dictionary::Entry;
499    ///
500    /// let mut dict = plist::Dictionary::new();
501    /// dict.insert("serde".to_owned(), 12.into());
502    ///
503    /// match dict.entry("serde") {
504    ///     Entry::Occupied(occupied) => assert_eq!(occupied.get(), &Value::from(12)),
505    ///     Entry::Vacant(_) => unimplemented!(),
506    /// }
507    /// ```
508    #[inline]
509    pub fn get(&self) -> &Value {
510        self.occupied.get()
511    }
512
513    /// Gets a mutable reference to the value in the entry.
514    ///
515    /// # Examples
516    ///
517    /// ```
518    /// use plist::Value;
519    /// use plist::dictionary::Entry;
520    ///
521    /// let mut dict = plist::Dictionary::new();
522    /// dict.insert("serde".to_owned(), Value::Array(vec![1.into(), 2.into(), 3.into()]));
523    ///
524    /// match dict.entry("serde") {
525    ///     Entry::Occupied(mut occupied) => {
526    ///         occupied.get_mut().as_array_mut().unwrap().push(4.into());
527    ///     }
528    ///     Entry::Vacant(_) => unimplemented!(),
529    /// }
530    ///
531    /// assert_eq!(dict["serde"].as_array().unwrap().len(), 4);
532    /// ```
533    #[inline]
534    pub fn get_mut(&mut self) -> &mut Value {
535        self.occupied.get_mut()
536    }
537
538    /// Converts the entry into a mutable reference to its value.
539    ///
540    /// # Examples
541    ///
542    /// ```
543    /// use plist::Value;
544    /// use plist::dictionary::Entry;
545    ///
546    /// let mut dict = plist::Dictionary::new();
547    /// dict.insert("serde".to_owned(), Value::Array(vec![1.into(), 2.into(), 3.into()]));
548    ///
549    /// match dict.entry("serde") {
550    ///     Entry::Occupied(mut occupied) => {
551    ///         occupied.into_mut().as_array_mut().unwrap().push(4.into());
552    ///     }
553    ///     Entry::Vacant(_) => unimplemented!(),
554    /// }
555    ///
556    /// assert_eq!(dict["serde"].as_array().unwrap().len(), 4);
557    /// ```
558    #[inline]
559    pub fn into_mut(self) -> &'a mut Value {
560        self.occupied.into_mut()
561    }
562
563    /// Sets the value of the entry with the `OccupiedEntry`'s key, and returns
564    /// the entry's old value.
565    ///
566    /// # Examples
567    ///
568    /// ```
569    /// use plist::Value;
570    /// use plist::dictionary::Entry;
571    ///
572    /// let mut dict = plist::Dictionary::new();
573    /// dict.insert("serde".to_owned(), 12.into());
574    ///
575    /// match dict.entry("serde") {
576    ///     Entry::Occupied(mut occupied) => {
577    ///         assert_eq!(occupied.insert(13.into()), 12.into());
578    ///         assert_eq!(occupied.get(), &Value::from(13));
579    ///     }
580    ///     Entry::Vacant(_) => unimplemented!(),
581    /// }
582    /// ```
583    #[inline]
584    pub fn insert(&mut self, value: Value) -> Value {
585        self.occupied.insert(value)
586    }
587
588    /// Takes the value of the entry out of the dictionary, and returns it.
589    ///
590    /// # Examples
591    ///
592    /// ```
593    /// use plist::dictionary::Entry;
594    ///
595    /// let mut dict = plist::Dictionary::new();
596    /// dict.insert("serde".to_owned(), 12.into());
597    ///
598    /// match dict.entry("serde") {
599    ///     Entry::Occupied(occupied) => assert_eq!(occupied.remove(), 12.into()),
600    ///     Entry::Vacant(_) => unimplemented!(),
601    /// }
602    /// ```
603    #[inline]
604    pub fn remove(self) -> Value {
605        self.occupied.remove()
606    }
607}
608
609//////////////////////////////////////////////////////////////////////////////
610
611impl<'a> IntoIterator for &'a Dictionary {
612    type Item = (&'a String, &'a Value);
613    type IntoIter = Iter<'a>;
614    #[inline]
615    fn into_iter(self) -> Self::IntoIter {
616        Iter {
617            iter: self.map.iter(),
618        }
619    }
620}
621
622/// An iterator over a plist::Dictionary's entries.
623pub struct Iter<'a> {
624    iter: IterImpl<'a>,
625}
626
627type IterImpl<'a> = map::Iter<'a, String, Value>;
628
629delegate_iterator!((Iter<'a>) => (&'a String, &'a Value));
630
631//////////////////////////////////////////////////////////////////////////////
632
633impl<'a> IntoIterator for &'a mut Dictionary {
634    type Item = (&'a String, &'a mut Value);
635    type IntoIter = IterMut<'a>;
636    #[inline]
637    fn into_iter(self) -> Self::IntoIter {
638        IterMut {
639            iter: self.map.iter_mut(),
640        }
641    }
642}
643
644/// A mutable iterator over a plist::Dictionary's entries.
645pub struct IterMut<'a> {
646    iter: map::IterMut<'a, String, Value>,
647}
648
649delegate_iterator!((IterMut<'a>) => (&'a String, &'a mut Value));
650
651//////////////////////////////////////////////////////////////////////////////
652
653impl IntoIterator for Dictionary {
654    type Item = (String, Value);
655    type IntoIter = IntoIter;
656    #[inline]
657    fn into_iter(self) -> Self::IntoIter {
658        IntoIter {
659            iter: self.map.into_iter(),
660        }
661    }
662}
663
664/// An owning iterator over a plist::Dictionary's entries.
665pub struct IntoIter {
666    iter: map::IntoIter<String, Value>,
667}
668
669delegate_iterator!((IntoIter) => (String, Value));
670
671//////////////////////////////////////////////////////////////////////////////
672
673/// An iterator over a plist::Dictionary's keys.
674pub struct Keys<'a> {
675    iter: map::Keys<'a, String, Value>,
676}
677
678delegate_iterator!((Keys<'a>) => &'a String);
679
680//////////////////////////////////////////////////////////////////////////////
681
682/// An iterator over a plist::Dictionary's values.
683pub struct Values<'a> {
684    iter: map::Values<'a, String, Value>,
685}
686
687delegate_iterator!((Values<'a>) => &'a Value);
688
689//////////////////////////////////////////////////////////////////////////////
690
691/// A mutable iterator over a plist::Dictionary's values.
692pub struct ValuesMut<'a> {
693    iter: map::ValuesMut<'a, String, Value>,
694}
695
696delegate_iterator!((ValuesMut<'a>) => &'a mut Value);