Skip to main content

minijinja/value/
object.rs

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