liquid_core/model/object/
map.rs

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