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);