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