minijinja/value/
object.rs

1use std::any::Any;
2use std::borrow::Cow;
3use std::cmp::Ordering;
4use std::collections::BTreeMap;
5use std::fmt;
6use std::hash::Hash;
7use std::sync::Arc;
8
9use crate::error::{Error, ErrorKind};
10use crate::value::{mapped_enumerator, Value};
11use crate::vm::State;
12
13/// A trait that represents a dynamic object.
14///
15/// There is a type erased wrapper of this trait available called
16/// [`DynObject`] which is what the engine actually holds internally.
17///
18/// # Basic Struct
19///
20/// The following example shows how to implement a dynamic object which
21/// represents a struct.  All that's needed is to implement
22/// [`get_value`](Self::get_value) to look up a field by name as well as
23/// [`enumerate`](Self::enumerate) to return an enumerator over the known keys.
24/// The [`repr`](Self::repr) defaults to `Map` so nothing needs to be done here.
25///
26/// ```
27/// use std::sync::Arc;
28/// use minijinja::value::{Value, Object, Enumerator};
29///
30/// #[derive(Debug)]
31/// struct Point(f32, f32, f32);
32///
33/// impl Object for Point {
34///     fn get_value(self: &Arc<Self>, key: &Value) -> Option<Value> {
35///         match key.as_str()? {
36///             "x" => Some(Value::from(self.0)),
37///             "y" => Some(Value::from(self.1)),
38///             "z" => Some(Value::from(self.2)),
39///             _ => None,
40///         }
41///     }
42///
43///     fn enumerate(self: &Arc<Self>) -> Enumerator {
44///         Enumerator::Str(&["x", "y", "z"])
45///     }
46/// }
47///
48/// let value = Value::from_object(Point(1.0, 2.5, 3.0));
49/// ```
50///
51/// # Basic Sequence
52///
53/// The following example shows how to implement a dynamic object which
54/// represents a sequence.  All that's needed is to implement
55/// [`repr`](Self::repr) to indicate that this is a sequence,
56/// [`get_value`](Self::get_value) to look up a field by index, and
57/// [`enumerate`](Self::enumerate) to return a sequential enumerator.
58/// This enumerator will automatically call `get_value` from `0..length`.
59///
60/// ```
61/// use std::sync::Arc;
62/// use minijinja::value::{Value, Object, ObjectRepr, Enumerator};
63///
64/// #[derive(Debug)]
65/// struct Point(f32, f32, f32);
66///
67/// impl Object for Point {
68///     fn repr(self: &Arc<Self>) -> ObjectRepr {
69///         ObjectRepr::Seq
70///     }
71///
72///     fn get_value(self: &Arc<Self>, key: &Value) -> Option<Value> {
73///         match key.as_usize()? {
74///             0 => Some(Value::from(self.0)),
75///             1 => Some(Value::from(self.1)),
76///             2 => Some(Value::from(self.2)),
77///             _ => None,
78///         }
79///     }
80///
81///     fn enumerate(self: &Arc<Self>) -> Enumerator {
82///         Enumerator::Seq(3)
83///     }
84/// }
85///
86/// let value = Value::from_object(Point(1.0, 2.5, 3.0));
87/// ```
88///
89/// # Iterables
90///
91/// If you have something that is not quite a sequence but is capable of yielding
92/// values over time, you can directly implement an iterable.  This is somewhat
93/// uncommon as you can normally directly use [`Value::make_iterable`].  Here
94/// is how this can be done though:
95///
96/// ```
97/// use std::sync::Arc;
98/// use minijinja::value::{Value, Object, ObjectRepr, Enumerator};
99///
100/// #[derive(Debug)]
101/// struct Range10;
102///
103/// impl Object for Range10 {
104///     fn repr(self: &Arc<Self>) -> ObjectRepr {
105///         ObjectRepr::Iterable
106///     }
107///
108///     fn enumerate(self: &Arc<Self>) -> Enumerator {
109///         Enumerator::Iter(Box::new((1..10).map(Value::from)))
110///     }
111/// }
112///
113/// let value = Value::from_object(Range10);
114/// ```
115///
116/// Iteration is encouraged to fail immediately (object is not iterable) or not at
117/// all.  However this is not always possible, but the iteration interface itself
118/// does not support fallible iteration.  It is however possible to accomplish the
119/// same thing by creating an [invalid value](index.html#invalid-values).
120///
121/// # Map As Context
122///
123/// Map can also be used as template rendering context.  This has a lot of
124/// benefits as it means that the serialization overhead can be largely to
125/// completely avoided.  This means that even if templates take hundreds of
126/// values, MiniJinja does not spend time eagerly converting them into values.
127///
128/// Here is a very basic example of how a template can be rendered with a dynamic
129/// context.  Note that the implementation of [`enumerate`](Self::enumerate)
130/// is optional for this to work.  It's in fact not used by the engine during
131/// rendering but it is necessary for the [`debug()`](crate::functions::debug)
132/// function to be able to show which values exist in the context.
133///
134/// ```
135/// # fn main() -> Result<(), minijinja::Error> {
136/// # use minijinja::Environment;
137/// use std::sync::Arc;
138/// use minijinja::value::{Value, Object};
139///
140/// #[derive(Debug)]
141/// pub struct DynamicContext {
142///     magic: i32,
143/// }
144///
145/// impl Object for DynamicContext {
146///     fn get_value(self: &Arc<Self>, field: &Value) -> Option<Value> {
147///         match field.as_str()? {
148///             "pid" => Some(Value::from(std::process::id())),
149///             "env" => Some(Value::from_iter(std::env::vars())),
150///             "magic" => Some(Value::from(self.magic)),
151///             _ => None,
152///         }
153///     }
154/// }
155///
156/// # let env = Environment::new();
157/// let tmpl = env.template_from_str("HOME={{ env.HOME }}; PID={{ pid }}; MAGIC={{ magic }}")?;
158/// let ctx = Value::from_object(DynamicContext { magic: 42 });
159/// let rv = tmpl.render(ctx)?;
160/// # Ok(()) }
161/// ```
162///
163/// One thing of note here is that in the above example `env` would be re-created every
164/// time the template needs it.  A better implementation would cache the value after it
165/// was created first.
166pub trait Object: fmt::Debug + Send + Sync {
167    /// Indicates the natural representation of an object.
168    ///
169    /// The default implementation returns [`ObjectRepr::Map`].
170    fn repr(self: &Arc<Self>) -> ObjectRepr {
171        ObjectRepr::Map
172    }
173
174    /// Given a key, looks up the associated value.
175    fn get_value(self: &Arc<Self>, key: &Value) -> Option<Value> {
176        let _ = key;
177        None
178    }
179
180    /// Enumerates the object.
181    ///
182    /// The engine uses the returned enumerator to implement iteration and
183    /// the size information of an object.  For more information see
184    /// [`Enumerator`].  The default implementation returns `Empty` for
185    /// all object representations other than [`ObjectRepr::Plain`] which
186    /// default to `NonEnumerable`.
187    ///
188    /// When wrapping other objects you might want to consider using
189    /// [`ObjectExt::mapped_enumerator`] and [`ObjectExt::mapped_rev_enumerator`].
190    fn enumerate(self: &Arc<Self>) -> Enumerator {
191        match self.repr() {
192            ObjectRepr::Plain => Enumerator::NonEnumerable,
193            ObjectRepr::Iterable | ObjectRepr::Map | ObjectRepr::Seq => Enumerator::Empty,
194        }
195    }
196
197    /// Returns the length of the enumerator.
198    ///
199    /// By default the length is taken by calling [`enumerate`](Self::enumerate) and
200    /// inspecting the [`Enumerator`].  This means that in order to determine
201    /// the length, an iteration is started.  If you think this is a problem for your
202    /// uses, you can manually implement this.  This might for instance be
203    /// needed if your type can only be iterated over once.
204    fn enumerator_len(self: &Arc<Self>) -> Option<usize> {
205        self.enumerate().query_len()
206    }
207
208    /// Returns `true` if this object is considered true for if conditions.
209    ///
210    /// The default implementation checks if the [`enumerator_len`](Self::enumerator_len)
211    /// is not `Some(0)` which is the recommended behavior for objects.
212    fn is_true(self: &Arc<Self>) -> bool {
213        self.enumerator_len() != Some(0)
214    }
215
216    /// The engine calls this to invoke the object itself.
217    ///
218    /// The default implementation returns an
219    /// [`InvalidOperation`](crate::ErrorKind::InvalidOperation) error.
220    fn call(self: &Arc<Self>, state: &State<'_, '_>, args: &[Value]) -> Result<Value, Error> {
221        let (_, _) = (state, args);
222        Err(Error::new(
223            ErrorKind::InvalidOperation,
224            "object is not callable",
225        ))
226    }
227
228    /// The engine calls this to invoke a method on the object.
229    ///
230    /// The default implementation returns an
231    /// [`UnknownMethod`](crate::ErrorKind::UnknownMethod) error.  When this error
232    /// is returned the engine will invoke the
233    /// [`unknown_method_callback`](crate::Environment::set_unknown_method_callback) of
234    /// the environment.
235    fn call_method(
236        self: &Arc<Self>,
237        state: &State<'_, '_>,
238        method: &str,
239        args: &[Value],
240    ) -> Result<Value, Error> {
241        if let Some(value) = self.get_value(&Value::from(method)) {
242            return value.call(state, args);
243        }
244
245        Err(Error::from(ErrorKind::UnknownMethod))
246    }
247
248    /// Custom comparison of this object against another object of the same type.
249    ///
250    /// This must return either `None` or `Some(Ordering)`.  When implemented this
251    /// must guarantee a total ordering as otherwise sort functions will crash.
252    /// This will only compare against other objects of the same type, not
253    /// anything else.  Objects of different types are given an absolute
254    /// ordering outside the scope of this method.
255    ///
256    /// The requirement is that an implementer downcasts the other [`DynObject`]
257    /// to itself, and it that cannot be accomplished `None` must be returned.
258    ///
259    /// ```rust
260    /// # use std::sync::Arc;
261    /// # use std::cmp::Ordering;
262    /// # use minijinja::value::{DynObject, Object};
263    /// # #[derive(Debug)]
264    /// # struct Thing { num: u32 };
265    /// impl Object for Thing {
266    ///     fn custom_cmp(self: &Arc<Self>, other: &DynObject) -> Option<Ordering> {
267    ///         let other = other.downcast_ref::<Self>()?;
268    ///         Some(self.num.cmp(&other.num))
269    ///     }
270    /// }
271    /// ```
272    fn custom_cmp(self: &Arc<Self>, other: &DynObject) -> Option<Ordering> {
273        let _ = other;
274        None
275    }
276
277    /// Formats the object for stringification.
278    ///
279    /// The default implementation is specific to the behavior of
280    /// [`repr`](Self::repr) and usually does not need modification.
281    fn render(self: &Arc<Self>, f: &mut fmt::Formatter<'_>) -> fmt::Result
282    where
283        Self: Sized + 'static,
284    {
285        match self.repr() {
286            ObjectRepr::Map => {
287                let mut dbg = f.debug_map();
288                for (key, value) in self.try_iter_pairs().into_iter().flatten() {
289                    dbg.entry(&key, &value);
290                }
291                dbg.finish()
292            }
293            // for either sequences or iterables, a length is needed, otherwise we
294            // don't want to risk iteration during printing and fall back to the
295            // debug print.
296            ObjectRepr::Seq | ObjectRepr::Iterable if self.enumerator_len().is_some() => {
297                let mut dbg = f.debug_list();
298                for value in self.try_iter().into_iter().flatten() {
299                    dbg.entry(&value);
300                }
301                dbg.finish()
302            }
303            _ => {
304                write!(f, "{self:?}")
305            }
306        }
307    }
308}
309
310macro_rules! impl_object_helpers {
311    ($vis:vis $self_ty: ty) => {
312        /// Iterates over this object.
313        ///
314        /// If this returns `None` then the default object iteration as defined by
315        /// the object's `enumeration` is used.
316        $vis fn try_iter(self: $self_ty) -> Option<Box<dyn Iterator<Item = Value> + Send + Sync>>
317        where
318            Self: 'static,
319        {
320            match self.enumerate() {
321                Enumerator::NonEnumerable => None,
322                Enumerator::Empty => Some(Box::new(None::<Value>.into_iter())),
323                Enumerator::Seq(l) => {
324                    let self_clone = self.clone();
325                    Some(Box::new((0..l).map(move |idx| {
326                        self_clone.get_value(&Value::from(idx)).unwrap_or_default()
327                    })))
328                }
329                Enumerator::Iter(iter) => Some(iter),
330                Enumerator::RevIter(iter) => Some(Box::new(iter)),
331                Enumerator::Str(s) => Some(Box::new(s.iter().copied().map(Value::from))),
332                Enumerator::Values(v) => Some(Box::new(v.into_iter())),
333            }
334        }
335
336        /// Iterate over key and value at once.
337        $vis fn try_iter_pairs(
338            self: $self_ty,
339        ) -> Option<Box<dyn Iterator<Item = (Value, Value)> + Send + Sync>> {
340            let iter = some!(self.try_iter());
341            let repr = self.repr();
342            let self_clone = self.clone();
343            Some(Box::new(iter.enumerate().map(move |(idx, item)| {
344                match repr {
345                    ObjectRepr::Map => {
346                        let value = self_clone.get_value(&item);
347                        (item, value.unwrap_or_default())
348                    }
349                    _ => (Value::from(idx), item)
350                }
351            })))
352        }
353    };
354}
355
356/// Provides utility methods for working with objects.
357pub trait ObjectExt: Object + Send + Sync + 'static {
358    /// Creates a new iterator enumeration that projects into the given object.
359    ///
360    /// It takes a method that is passed a reference to `self` and is expected
361    /// to return an [`Iterator`].  This iterator is then wrapped in an
362    /// [`Enumerator::Iter`].  This allows one to create an iterator that borrows
363    /// out of the object.
364    ///
365    /// # Example
366    ///
367    /// ```
368    /// # use std::collections::HashMap;
369    /// use std::sync::Arc;
370    /// use minijinja::value::{Value, Object, ObjectExt, Enumerator};
371    ///
372    /// #[derive(Debug)]
373    /// struct CustomMap(HashMap<usize, i64>);
374    ///
375    /// impl Object for CustomMap {
376    ///     fn get_value(self: &Arc<Self>, key: &Value) -> Option<Value> {
377    ///         self.0.get(&key.as_usize()?).copied().map(Value::from)
378    ///     }
379    ///
380    ///     fn enumerate(self: &Arc<Self>) -> Enumerator {
381    ///         self.mapped_enumerator(|this| {
382    ///             Box::new(this.0.keys().copied().map(Value::from))
383    ///         })
384    ///     }
385    /// }
386    /// ```
387    fn mapped_enumerator<F>(self: &Arc<Self>, maker: F) -> Enumerator
388    where
389        F: for<'a> FnOnce(&'a Self) -> Box<dyn Iterator<Item = Value> + Send + Sync + 'a>
390            + Send
391            + Sync
392            + 'static,
393        Self: Sized,
394    {
395        mapped_enumerator(self, maker)
396    }
397
398    /// Creates a new reversible iterator enumeration that projects into the given object.
399    ///
400    /// It takes a method that is passed a reference to `self` and is expected
401    /// to return a [`DoubleEndedIterator`].  This iterator is then wrapped in an
402    /// [`Enumerator::RevIter`].  This allows one to create an iterator that borrows
403    /// out of the object and is reversible.
404    ///
405    /// # Example
406    ///
407    /// ```
408    /// # use std::collections::HashMap;
409    /// use std::sync::Arc;
410    /// use std::ops::Range;
411    /// use minijinja::value::{Value, Object, ObjectExt, ObjectRepr, Enumerator};
412    ///
413    /// #[derive(Debug)]
414    /// struct VecView(Vec<usize>);
415    ///
416    /// impl Object for VecView {
417    ///     fn repr(self: &Arc<Self>) -> ObjectRepr {
418    ///         ObjectRepr::Iterable
419    ///     }
420    ///
421    ///     fn enumerate(self: &Arc<Self>) -> Enumerator {
422    ///         self.mapped_enumerator(|this| {
423    ///             Box::new(this.0.iter().cloned().map(Value::from))
424    ///         })
425    ///     }
426    /// }
427    /// ```
428    fn mapped_rev_enumerator<F>(self: &Arc<Self>, maker: F) -> Enumerator
429    where
430        F: for<'a> FnOnce(
431                &'a Self,
432            )
433                -> Box<dyn DoubleEndedIterator<Item = Value> + Send + Sync + 'a>
434            + Send
435            + Sync
436            + 'static,
437        Self: Sized,
438    {
439        // Taken from `mapped_enumerator`.
440
441        struct Iter {
442            iter: Box<dyn DoubleEndedIterator<Item = Value> + Send + Sync + 'static>,
443            _object: DynObject,
444        }
445
446        impl Iterator for Iter {
447            type Item = Value;
448
449            fn next(&mut self) -> Option<Self::Item> {
450                self.iter.next()
451            }
452
453            fn size_hint(&self) -> (usize, Option<usize>) {
454                self.iter.size_hint()
455            }
456        }
457
458        impl DoubleEndedIterator for Iter {
459            fn next_back(&mut self) -> Option<Self::Item> {
460                self.iter.next_back()
461            }
462        }
463
464        // SAFETY: this is safe because the `Iter` will keep our object alive.
465        let iter = unsafe {
466            std::mem::transmute::<
467                Box<dyn DoubleEndedIterator<Item = _>>,
468                Box<dyn DoubleEndedIterator<Item = _> + Send + Sync>,
469            >(maker(self))
470        };
471        let _object = DynObject::new(self.clone());
472        Enumerator::RevIter(Box::new(Iter { iter, _object }))
473    }
474
475    impl_object_helpers!(&Arc<Self>);
476}
477
478impl<T: Object + Send + Sync + 'static> ObjectExt for T {}
479
480/// Enumerators help define iteration behavior for [`Object`]s.
481///
482/// When Jinja wants to know the length of an object, if it's empty or
483/// not or if it wants to iterate over it, it will ask the [`Object`] to
484/// enumerate itself with the [`enumerate`](Object::enumerate) method.  The
485/// returned enumerator has enough information so that the object can be
486/// iterated over, but it does not necessarily mean that iteration actually
487/// starts or that it has the data to yield the right values.
488///
489/// In fact, you should never inspect an enumerator.  You can create it or
490/// forward it.  For actual iteration use [`ObjectExt::try_iter`] etc.
491#[non_exhaustive]
492pub enum Enumerator {
493    /// Marks non enumerable objects.
494    ///
495    /// Such objects cannot be iterated over, the length is unknown which
496    /// means they are not considered empty by the engine.  This is a good
497    /// choice for plain objects.
498    ///
499    /// | Iterable | Length  |
500    /// |----------|---------|
501    /// | no       | unknown |
502    NonEnumerable,
503
504    /// The empty enumerator.  It yields no elements.
505    ///
506    /// | Iterable | Length      |
507    /// |----------|-------------|
508    /// | yes      | known (`0`) |
509    Empty,
510
511    /// A slice of static strings.
512    ///
513    /// This is a useful enumerator to enumerate the attributes of an
514    /// object or the keys in a string hash map.
515    ///
516    /// | Iterable | Length       |
517    /// |----------|--------------|
518    /// | yes      | known        |
519    Str(&'static [&'static str]),
520
521    /// A dynamic iterator over values.
522    ///
523    /// The length is known if the [`Iterator::size_hint`] has matching lower
524    /// and upper bounds.  The logic used by the engine is the following:
525    ///
526    /// ```
527    /// # let iter = Some(1).into_iter();
528    /// let len = match iter.size_hint() {
529    ///     (lower, Some(upper)) if lower == upper => Some(lower),
530    ///     _ => None
531    /// };
532    /// ```
533    ///
534    /// Because the engine prefers repeatable iteration, it will keep creating
535    /// new enumerators every time the iteration should restart.  Sometimes
536    /// that might not always be possible (eg: you stream data in) in which
537    /// case
538    ///
539    /// | Iterable | Length          |
540    /// |----------|-----------------|
541    /// | yes      | sometimes known |
542    Iter(Box<dyn Iterator<Item = Value> + Send + Sync>),
543
544    /// Like `Iter` but supports efficient reversing.
545    ///
546    /// This means that the iterator has to be of type [`DoubleEndedIterator`].
547    ///
548    /// | Iterable | Length          |
549    /// |----------|-----------------|
550    /// | yes      | sometimes known |
551    RevIter(Box<dyn DoubleEndedIterator<Item = Value> + Send + Sync>),
552
553    /// Indicates sequential iteration.
554    ///
555    /// This instructs the engine to iterate over an object by enumerating it
556    /// from `0` to `n` by calling [`Object::get_value`].  This is essentially the
557    /// way sequences are supposed to be enumerated.
558    ///
559    /// | Iterable | Length          |
560    /// |----------|-----------------|
561    /// | yes      | known           |
562    Seq(usize),
563
564    /// A vector of known values to iterate over.
565    ///
566    /// The iterator will yield each value in the vector one after another.
567    ///
568    /// | Iterable | Length          |
569    /// |----------|-----------------|
570    /// | yes      | known           |
571    Values(Vec<Value>),
572}
573
574/// Defines the natural representation of this object.
575///
576/// An [`ObjectRepr`] is a reduced form of
577/// [`ValueKind`](crate::value::ValueKind) which only contains value which can
578/// be represented by objects.  For instance an object can never be a primitive
579/// and as such those kinds are unavailable.
580///
581/// The representation influences how values are serialized, stringified or
582/// what kind they report.
583#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
584#[non_exhaustive]
585pub enum ObjectRepr {
586    /// An object that has no reasonable representation.
587    ///
588    /// - **Default Render:** [`Debug`]
589    /// - **Collection Behavior:** none
590    /// - **Iteration Behavior:** none
591    /// - **Serialize:** [`Debug`] / [`render`](Object::render) output as string
592    Plain,
593
594    /// Represents a map or object.
595    ///
596    /// - **Default Render:** `{key: value,...}` pairs
597    /// - **Collection Behavior:** looks like a map, can be indexed by key, has a length
598    /// - **Iteration Behavior:** iterates over keys
599    /// - **Serialize:** Serializes as map
600    Map,
601
602    /// Represents a sequence (eg: array/list).
603    ///
604    /// - **Default Render:** `[value,...]`
605    /// - **Collection Behavior:** looks like a list, can be indexed by index, has a length
606    /// - **Iteration Behavior:** iterates over values
607    /// - **Serialize:** Serializes as list
608    Seq,
609
610    /// Represents a non indexable, iterable object.
611    ///
612    /// - **Default Render:** `[value,...]` (if length is known), `"<iterator>"` otherwise.
613    /// - **Collection Behavior:** looks like a list if length is known, cannot be indexed
614    /// - **Iteration Behavior:** iterates over values
615    /// - **Serialize:** Serializes as list
616    Iterable,
617}
618
619type_erase! {
620    pub trait Object => DynObject {
621        fn repr(&self) -> ObjectRepr;
622
623        fn get_value(&self, key: &Value) -> Option<Value>;
624
625        fn enumerate(&self) -> Enumerator;
626
627        fn is_true(&self) -> bool;
628
629        fn enumerator_len(&self) -> Option<usize>;
630
631        fn call(
632            &self,
633            state: &State<'_, '_>,
634            args: &[Value]
635        ) -> Result<Value, Error>;
636
637        fn call_method(
638            &self,
639            state: &State<'_, '_>,
640            method: &str,
641            args: &[Value]
642        ) -> Result<Value, Error>;
643
644        fn custom_cmp(&self, other: &DynObject) -> Option<Ordering>;
645
646        fn render(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result;
647
648        impl fmt::Debug {
649            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result;
650        }
651    }
652}
653
654unsafe impl Send for DynObject {}
655unsafe impl Sync for DynObject {}
656
657impl DynObject {
658    impl_object_helpers!(pub &Self);
659
660    /// Checks if this dyn object is the same as another.
661    pub(crate) fn is_same_object(&self, other: &DynObject) -> bool {
662        self.ptr == other.ptr && self.vtable == other.vtable
663    }
664
665    /// Checks if the two dyn objects are of the same type.
666    pub(crate) fn is_same_object_type(&self, other: &DynObject) -> bool {
667        self.type_id() == other.type_id()
668    }
669}
670
671impl Hash for DynObject {
672    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
673        if let Some(iter) = self.try_iter_pairs() {
674            for (key, value) in iter {
675                key.hash(state);
676                value.hash(state);
677            }
678        }
679    }
680}
681
682impl fmt::Display for DynObject {
683    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
684        self.render(f)
685    }
686}
687
688impl Enumerator {
689    fn query_len(&self) -> Option<usize> {
690        Some(match self {
691            Enumerator::Empty => 0,
692            Enumerator::Values(v) => v.len(),
693            Enumerator::Str(v) => v.len(),
694            Enumerator::Iter(i) => match i.size_hint() {
695                (a, Some(b)) if a == b => a,
696                _ => return None,
697            },
698            Enumerator::RevIter(i) => match i.size_hint() {
699                (a, Some(b)) if a == b => a,
700                _ => return None,
701            },
702            Enumerator::Seq(v) => *v,
703            Enumerator::NonEnumerable => return None,
704        })
705    }
706}
707
708macro_rules! impl_value_vec {
709    ($vec_type:ident) => {
710        impl<T> Object for $vec_type<T>
711        where
712            T: Into<Value> + Clone + Send + Sync + fmt::Debug + 'static,
713        {
714            fn repr(self: &Arc<Self>) -> ObjectRepr {
715                ObjectRepr::Seq
716            }
717
718            #[inline(always)]
719            fn get_value(self: &Arc<Self>, key: &Value) -> Option<Value> {
720                self.get(some!(key.as_usize())).cloned().map(|v| v.into())
721            }
722
723            fn enumerate(self: &Arc<Self>) -> Enumerator {
724                Enumerator::Seq(self.len())
725            }
726        }
727
728        impl<T> From<$vec_type<T>> for Value
729        where
730            T: Into<Value> + Clone + Send + Sync + fmt::Debug + 'static,
731        {
732            fn from(val: $vec_type<T>) -> Self {
733                Value::from_object(val)
734            }
735        }
736    };
737}
738
739#[allow(unused)]
740macro_rules! impl_value_iterable {
741    ($iterable_type:ident, $enumerator:ident) => {
742        impl<T> Object for $iterable_type<T>
743        where
744            T: Into<Value> + Clone + Send + Sync + fmt::Debug + 'static,
745        {
746            fn repr(self: &Arc<Self>) -> ObjectRepr {
747                ObjectRepr::Iterable
748            }
749
750            fn enumerate(self: &Arc<Self>) -> Enumerator {
751                self.clone()
752                    .$enumerator(|this| Box::new(this.iter().map(|x| x.clone().into())))
753            }
754        }
755
756        impl<T> From<$iterable_type<T>> for Value
757        where
758            T: Into<Value> + Clone + Send + Sync + fmt::Debug + 'static,
759        {
760            fn from(val: $iterable_type<T>) -> Self {
761                Value::from_object(val)
762            }
763        }
764    };
765}
766
767macro_rules! impl_str_map_helper {
768    ($map_type:ident, $key_type:ty, $enumerator:ident) => {
769        impl<V> Object for $map_type<$key_type, V>
770        where
771            V: Into<Value> + Clone + Send + Sync + fmt::Debug + 'static,
772        {
773            #[inline(always)]
774            fn get_value(self: &Arc<Self>, key: &Value) -> Option<Value> {
775                self.get(some!(key.as_str())).cloned().map(|v| v.into())
776            }
777
778            fn enumerate(self: &Arc<Self>) -> Enumerator {
779                self.$enumerator(|this| Box::new(this.keys().map(|x| Value::from(x as &str))))
780            }
781
782            fn enumerator_len(self: &Arc<Self>) -> Option<usize> {
783                Some(self.len())
784            }
785        }
786    };
787}
788
789macro_rules! impl_str_map {
790    ($map_type:ident, $enumerator:ident) => {
791        impl_str_map_helper!($map_type, String, $enumerator);
792        impl_str_map_helper!($map_type, Arc<str>, $enumerator);
793
794        impl<V> From<$map_type<String, V>> for Value
795        where
796            V: Into<Value> + Send + Sync + Clone + fmt::Debug + 'static,
797        {
798            fn from(val: $map_type<String, V>) -> Self {
799                Value::from_object(val)
800            }
801        }
802
803        impl<V> From<$map_type<Arc<str>, V>> for Value
804        where
805            V: Into<Value> + Send + Sync + Clone + fmt::Debug + 'static,
806        {
807            fn from(val: $map_type<Arc<str>, V>) -> Self {
808                Value::from_object(val)
809            }
810        }
811
812        impl<'a, V> From<$map_type<&'a str, V>> for Value
813        where
814            V: Into<Value> + Send + Sync + Clone + fmt::Debug + 'static,
815        {
816            fn from(val: $map_type<&'a str, V>) -> Self {
817                Value::from(
818                    val.into_iter()
819                        .map(|(k, v)| (Arc::from(k), v))
820                        .collect::<$map_type<Arc<str>, V>>(),
821                )
822            }
823        }
824
825        impl<'a, V> From<$map_type<Cow<'a, str>, V>> for Value
826        where
827            V: Into<Value> + Send + Sync + Clone + fmt::Debug + 'static,
828        {
829            fn from(val: $map_type<Cow<'a, str>, V>) -> Self {
830                Value::from(
831                    val.into_iter()
832                        .map(|(k, v)| (Arc::from(k), v))
833                        .collect::<$map_type<Arc<str>, V>>(),
834                )
835            }
836        }
837    };
838}
839
840macro_rules! impl_value_map {
841    ($map_type:ident, $enumerator:ident) => {
842        impl<V> Object for $map_type<Value, V>
843        where
844            V: Into<Value> + Clone + Send + Sync + fmt::Debug + 'static,
845        {
846            #[inline(always)]
847            fn get_value(self: &Arc<Self>, key: &Value) -> Option<Value> {
848                self.get(key).cloned().map(|v| v.into())
849            }
850
851            fn enumerate(self: &Arc<Self>) -> Enumerator {
852                self.$enumerator(|this| Box::new(this.keys().cloned()))
853            }
854
855            fn enumerator_len(self: &Arc<Self>) -> Option<usize> {
856                Some(self.len())
857            }
858        }
859
860        impl<V> From<$map_type<Value, V>> for Value
861        where
862            V: Into<Value> + Send + Sync + Clone + fmt::Debug + 'static,
863        {
864            fn from(val: $map_type<Value, V>) -> Self {
865                Value::from_object(val)
866            }
867        }
868    };
869}
870
871impl_value_vec!(Vec);
872impl_value_map!(BTreeMap, mapped_rev_enumerator);
873impl_str_map!(BTreeMap, mapped_rev_enumerator);
874
875#[cfg(feature = "std_collections")]
876mod std_collections_impls {
877    use super::*;
878    use std::collections::{BTreeSet, HashMap, HashSet, LinkedList, VecDeque};
879
880    impl_value_iterable!(LinkedList, mapped_rev_enumerator);
881    impl_value_iterable!(HashSet, mapped_enumerator);
882    impl_value_iterable!(BTreeSet, mapped_rev_enumerator);
883    impl_str_map!(HashMap, mapped_enumerator);
884    impl_value_map!(HashMap, mapped_enumerator);
885    impl_value_vec!(VecDeque);
886}
887
888#[cfg(feature = "preserve_order")]
889mod preserve_order_impls {
890    use super::*;
891    use indexmap::IndexMap;
892
893    impl_value_map!(IndexMap, mapped_rev_enumerator);
894}