minijinja/value/
object.rs

1use std::any::{Any, TypeId};
2use std::fmt;
3use std::ops::Range;
4use std::sync::{Arc, Mutex};
5
6use crate::error::{Error, ErrorKind};
7use crate::value::{intern, Value};
8use crate::vm::State;
9
10/// A utility trait that represents a dynamic object.
11///
12/// The engine uses the [`Value`] type to represent values that the engine
13/// knows about.  Most of these values are primitives such as integers, strings
14/// or maps.  However it is also possible to expose custom types without
15/// undergoing a serialization step to the engine.  For this to work a type
16/// needs to implement the [`Object`] trait and be wrapped in a value with
17/// [`Value::from_object`](crate::value::Value::from_object). The ownership of
18/// the object will then move into the value type.
19//
20/// The engine uses reference counted objects with interior mutability in the
21/// value type.  This means that all trait methods take `&self` and types like
22/// [`Mutex`](std::sync::Mutex) need to be used to enable mutability.
23//
24/// Objects need to implement [`Display`](std::fmt::Display) which is used by
25/// the engine to convert the object into a string if needed.  Additionally
26/// [`Debug`](std::fmt::Debug) is required as well.
27///
28/// The exact runtime characteristics of the object are influenced by the
29/// [`kind`](Self::kind) of the object.  By default an object can just be
30/// stringified and methods can be called.
31///
32/// For examples of how to implement objects refer to [`SeqObject`] and
33/// [`StructObject`].
34pub trait Object: fmt::Display + fmt::Debug + Any + Sync + Send {
35    /// Describes the kind of an object.
36    ///
37    /// If not implemented behavior for an object is [`ObjectKind::Plain`]
38    /// which just means that it's stringifyable and potentially can be
39    /// called or has methods.
40    ///
41    /// For more information see [`ObjectKind`].
42    fn kind(&self) -> ObjectKind<'_> {
43        ObjectKind::Plain
44    }
45
46    /// Called when the engine tries to call a method on the object.
47    ///
48    /// It's the responsibility of the implementer to ensure that an
49    /// error is generated if an invalid method is invoked.  If the method
50    /// is not known an [`ErrorKind::UnknownMethod`] error must be returned.
51    ///
52    /// To convert the arguments into arguments use the
53    /// [`from_args`](crate::value::from_args) function.
54    fn call_method(&self, state: &State, name: &str, args: &[Value]) -> Result<Value, Error> {
55        let _state = state;
56        let _args = args;
57        Err(Error::new(
58            ErrorKind::UnknownMethod,
59            format!("object has no method named {name}"),
60        ))
61    }
62
63    /// Called when the object is invoked directly.
64    ///
65    /// The default implementation just generates an error that the object
66    /// cannot be invoked.
67    ///
68    /// To convert the arguments into arguments use the
69    /// [`from_args`](crate::value::from_args) function.
70    fn call(&self, state: &State, args: &[Value]) -> Result<Value, Error> {
71        let _state = state;
72        let _args = args;
73        Err(Error::new(
74            ErrorKind::InvalidOperation,
75            "tried to call non callable object",
76        ))
77    }
78}
79
80impl dyn Object {
81    /// Returns some reference to the boxed object if it is of type `T`, or None if it isn’t.
82    ///
83    /// This is basically the "reverse" of [`from_object`](Value::from_object),
84    /// [`from_seq_object`](Value::from_seq_object) and [`from_struct_object`](Value::from_struct_object).
85    ///
86    /// Because this method works also for objects that only implement [`StructObject`]
87    /// and [`SeqObject`] these methods do not actually use trait bounds that are
88    /// restricted to `Object`.
89    ///
90    /// # Example
91    ///
92    /// ```rust
93    /// # use minijinja::value::{Value, Object};
94    /// use std::fmt;
95    ///
96    /// #[derive(Debug)]
97    /// struct Thing {
98    ///     id: usize,
99    /// }
100    ///
101    /// impl fmt::Display for Thing {
102    ///     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
103    ///         fmt::Debug::fmt(self, f)
104    ///     }
105    /// }
106    ///
107    /// impl Object for Thing {}
108    ///
109    /// let x_value = Value::from_object(Thing { id: 42 });
110    /// let value_as_obj = x_value.as_object().unwrap();
111    /// let thing = value_as_obj.downcast_ref::<Thing>().unwrap();
112    /// assert_eq!(thing.id, 42);
113    /// ```
114    ///
115    /// It also works with [`SeqObject`] or [`StructObject`]:
116    ///
117    /// ```rust
118    /// # use minijinja::value::{Value, SeqObject};
119    ///
120    /// struct Thing {
121    ///     id: usize,
122    /// }
123    ///
124    /// impl SeqObject for Thing {
125    ///     fn get_item(&self, idx: usize) -> Option<Value> {
126    ///         (idx < 3).then(|| Value::from(idx))
127    ///     }
128    ///     fn item_count(&self) -> usize {
129    ///         3
130    ///     }
131    /// }
132    ///
133    /// let x_value = Value::from_seq_object(Thing { id: 42 });
134    /// let value_as_obj = x_value.as_object().unwrap();
135    /// let thing = value_as_obj.downcast_ref::<Thing>().unwrap();
136    /// assert_eq!(thing.id, 42);
137    /// ```
138    pub fn downcast_ref<T: 'static>(&self) -> Option<&T> {
139        let type_id = (*self).type_id();
140        if type_id == TypeId::of::<T>() {
141            // SAFETY: type type id check ensures this type cast is correct
142            return Some(unsafe { &*(self as *const dyn Object as *const T) });
143        } else if type_id == TypeId::of::<SimpleSeqObject<T>>() {
144            // SAFETY: type type id check ensures this type cast is correct
145            let wrapper = unsafe { &*(self as *const dyn Object as *const SimpleSeqObject<T>) };
146            return Some(&wrapper.0);
147        } else if type_id == TypeId::of::<SimpleStructObject<T>>() {
148            // SAFETY: type type id check ensures this type cast is correct
149            let wrapper = unsafe { &*(self as *const dyn Object as *const SimpleStructObject<T>) };
150            return Some(&wrapper.0);
151        }
152        None
153    }
154
155    /// Checks if the object is of a specific type.
156    ///
157    /// For details of this operation see [`downcast_ref`](#method.downcast_ref).
158    pub fn is<T: 'static>(&self) -> bool {
159        let type_id = (*self).type_id();
160        type_id == TypeId::of::<T>()
161            || type_id == TypeId::of::<SimpleSeqObject<T>>()
162            || type_id == TypeId::of::<SimpleStructObject<T>>()
163    }
164}
165
166impl<T: Object> Object for Arc<T> {
167    #[inline]
168    fn kind(&self) -> ObjectKind<'_> {
169        T::kind(self)
170    }
171
172    #[inline]
173    fn call_method(&self, state: &State, name: &str, args: &[Value]) -> Result<Value, Error> {
174        T::call_method(self, state, name, args)
175    }
176
177    #[inline]
178    fn call(&self, state: &State, args: &[Value]) -> Result<Value, Error> {
179        T::call(self, state, args)
180    }
181}
182
183/// A kind defines the object's behavior.
184///
185/// When a dynamic [`Object`] is implemented, it can be of one of the kinds
186/// here.  The default behavior will be a [`Plain`](Self::Plain) object which
187/// doesn't do much other than that it can be printed.  For an object to turn
188/// into a [struct](Self::Struct) or [sequence](Self::Seq) the necessary kind
189/// has to be returned with a pointer to itself.
190///
191/// Today object's can have the behavior of structs and sequences but this
192/// might expand in the future.  It does mean that not all types of values can
193/// be represented by objects.
194#[non_exhaustive]
195pub enum ObjectKind<'a> {
196    /// This object is a plain object.
197    ///
198    /// Such an object has no attributes but it might be callable and it
199    /// can be stringified.  When serialized it's serialized in it's
200    /// stringified form.
201    Plain,
202
203    /// This object is a sequence.
204    ///
205    /// Requires that the object implements [`SeqObject`].
206    Seq(&'a dyn SeqObject),
207
208    /// This object is a struct (map with string keys).
209    ///
210    /// Requires that the object implements [`StructObject`].
211    Struct(&'a dyn StructObject),
212
213    /// This object is an iterator that yields new values.
214    ///
215    /// Requires that the object implements [`IteratorObject`].  It's not
216    /// recommended to implement this, instead one should directly pass
217    /// iterators to [`Value::make_one_shot_iterator`].
218    Iterator(&'a dyn IteratorObject),
219}
220
221/// Provides the behavior of an [`Object`] holding sequence of values.
222///
223/// An object holding a sequence of values (tuple, list etc.) can be
224/// represented by this trait.
225///
226/// # Simplified Example
227///
228/// For sequences which do not need any special method behavior, the [`Value`]
229/// type is capable of automatically constructing a wrapper [`Object`] by using
230/// [`Value::from_seq_object`].  In that case only [`SeqObject`] needs to be
231/// implemented and the value will provide default implementations for
232/// stringification and debug printing.
233///
234/// ```
235/// use minijinja::value::{Value, SeqObject};
236///
237/// struct Point(f32, f32, f32);
238///
239/// impl SeqObject for Point {
240///     fn get_item(&self, idx: usize) -> Option<Value> {
241///         match idx {
242///             0 => Some(Value::from(self.0)),
243///             1 => Some(Value::from(self.1)),
244///             2 => Some(Value::from(self.2)),
245///             _ => None,
246///         }
247///     }
248///
249///     fn item_count(&self) -> usize {
250///         3
251///     }
252/// }
253///
254/// let value = Value::from_seq_object(Point(1.0, 2.5, 3.0));
255/// ```
256///
257/// # Full Example
258///
259/// This example shows how one can use [`SeqObject`] in conjunction
260/// with a fully customized [`Object`].  Note that in this case not
261/// only [`Object`] needs to be implemented, but also [`Debug`] and
262/// [`Display`](std::fmt::Display) no longer come for free.
263///
264/// ```
265/// use std::fmt;
266/// use minijinja::value::{Value, Object, ObjectKind, SeqObject};
267///
268/// #[derive(Debug, Clone)]
269/// struct Point(f32, f32, f32);
270///
271/// impl fmt::Display for Point {
272///     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
273///         write!(f, "({}, {}, {})", self.0, self.1, self.2)
274///     }
275/// }
276///
277/// impl Object for Point {
278///     fn kind(&self) -> ObjectKind<'_> {
279///         ObjectKind::Seq(self)
280///     }
281/// }
282///
283/// impl SeqObject for Point {
284///     fn get_item(&self, idx: usize) -> Option<Value> {
285///         match idx {
286///             0 => Some(Value::from(self.0)),
287///             1 => Some(Value::from(self.1)),
288///             2 => Some(Value::from(self.2)),
289///             _ => None,
290///         }
291///     }
292///
293///     fn item_count(&self) -> usize {
294///         3
295///     }
296/// }
297///
298/// let value = Value::from_object(Point(1.0, 2.5, 3.0));
299/// ```
300pub trait SeqObject: Send + Sync {
301    /// Looks up an item by index.
302    ///
303    /// Sequences should provide a value for all items in the range of `0..item_count`
304    /// but the engine will assume that items within the range are `Undefined`
305    /// if `None` is returned.
306    fn get_item(&self, idx: usize) -> Option<Value>;
307
308    /// Returns the number of items in the sequence.
309    fn item_count(&self) -> usize;
310}
311
312impl dyn SeqObject + '_ {
313    /// Convenient iterator over a [`SeqObject`].
314    pub fn iter(&self) -> SeqObjectIter<'_> {
315        SeqObjectIter {
316            seq: self,
317            range: 0..self.item_count(),
318        }
319    }
320}
321
322impl<T: SeqObject> SeqObject for Arc<T> {
323    #[inline]
324    fn get_item(&self, idx: usize) -> Option<Value> {
325        T::get_item(self, idx)
326    }
327
328    #[inline]
329    fn item_count(&self) -> usize {
330        T::item_count(self)
331    }
332}
333
334impl<'a, T: SeqObject + ?Sized> SeqObject for &'a T {
335    #[inline]
336    fn get_item(&self, idx: usize) -> Option<Value> {
337        T::get_item(self, idx)
338    }
339
340    #[inline]
341    fn item_count(&self) -> usize {
342        T::item_count(self)
343    }
344}
345
346impl<T: Into<Value> + Send + Sync + Clone> SeqObject for [T] {
347    #[inline(always)]
348    fn get_item(&self, idx: usize) -> Option<Value> {
349        self.get(idx).cloned().map(Into::into)
350    }
351
352    #[inline(always)]
353    fn item_count(&self) -> usize {
354        self.len()
355    }
356}
357
358impl<T: Into<Value> + Send + Sync + Clone> SeqObject for Vec<T> {
359    #[inline(always)]
360    fn get_item(&self, idx: usize) -> Option<Value> {
361        self.get(idx).cloned().map(Into::into)
362    }
363
364    #[inline(always)]
365    fn item_count(&self) -> usize {
366        self.len()
367    }
368}
369
370/// Iterates over [`SeqObject`]
371pub struct SeqObjectIter<'a> {
372    seq: &'a dyn SeqObject,
373    range: Range<usize>,
374}
375
376impl<'a> Iterator for SeqObjectIter<'a> {
377    type Item = Value;
378
379    #[inline(always)]
380    fn next(&mut self) -> Option<Self::Item> {
381        self.range
382            .next()
383            .map(|idx| self.seq.get_item(idx).unwrap_or(Value::UNDEFINED))
384    }
385
386    #[inline(always)]
387    fn size_hint(&self) -> (usize, Option<usize>) {
388        self.range.size_hint()
389    }
390}
391
392impl<'a> DoubleEndedIterator for SeqObjectIter<'a> {
393    #[inline(always)]
394    fn next_back(&mut self) -> Option<Self::Item> {
395        self.range
396            .next_back()
397            .map(|idx| self.seq.get_item(idx).unwrap_or(Value::UNDEFINED))
398    }
399}
400
401impl<'a> ExactSizeIterator for SeqObjectIter<'a> {}
402
403/// Provides the behavior of an [`Object`] holding a struct.
404///
405/// An basic object with the shape and behavior of a struct (that means a
406/// map with string keys) can be represented by this trait.
407///
408/// # Simplified Example
409///
410/// For structs which do not need any special method behavior or methods, the
411/// [`Value`] type is capable of automatically constructing a wrapper [`Object`]
412/// by using [`Value::from_struct_object`].  In that case only [`StructObject`]
413/// needs to be implemented and the value will provide default implementations
414/// for stringification and debug printing.
415///
416/// ```
417/// use minijinja::value::{Value, StructObject};
418///
419/// struct Point(f32, f32, f32);
420///
421/// impl StructObject for Point {
422///     fn get_field(&self, name: &str) -> Option<Value> {
423///         match name {
424///             "x" => Some(Value::from(self.0)),
425///             "y" => Some(Value::from(self.1)),
426///             "z" => Some(Value::from(self.2)),
427///             _ => None,
428///         }
429///     }
430///
431///     fn static_fields(&self) -> Option<&'static [&'static str]> {
432///         Some(&["x", "y", "z"][..])
433///     }
434/// }
435///
436/// let value = Value::from_struct_object(Point(1.0, 2.5, 3.0));
437/// ```
438///
439/// # Full Example
440///
441/// The following example shows how to implement a dynamic object which
442/// represents a struct.  Note that in this case not only [`Object`] needs to be
443/// implemented, but also [`Debug`] and [`Display`](std::fmt::Display) no longer
444/// come for free.
445///
446/// ```
447/// use std::fmt;
448/// use minijinja::value::{Value, Object, ObjectKind, StructObject};
449///
450/// #[derive(Debug, Clone)]
451/// struct Point(f32, f32, f32);
452///
453/// impl fmt::Display for Point {
454///     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
455///         write!(f, "({}, {}, {})", self.0, self.1, self.2)
456///     }
457/// }
458///
459/// impl Object for Point {
460///     fn kind(&self) -> ObjectKind<'_> {
461///         ObjectKind::Struct(self)
462///     }
463/// }
464///
465/// impl StructObject for Point {
466///     fn get_field(&self, name: &str) -> Option<Value> {
467///         match name {
468///             "x" => Some(Value::from(self.0)),
469///             "y" => Some(Value::from(self.1)),
470///             "z" => Some(Value::from(self.2)),
471///             _ => None,
472///         }
473///     }
474///
475///     fn static_fields(&self) -> Option<&'static [&'static str]> {
476///         Some(&["x", "y", "z"][..])
477///     }
478/// }
479///
480/// let value = Value::from_object(Point(1.0, 2.5, 3.0));
481/// ```
482///
483/// # Struct As context
484///
485/// Structs can also be used as template rendering context.  This has a lot of
486/// benefits as it means that the serialization overhead can be largely to
487/// completely avoided.  This means that even if templates take hundreds of
488/// values, MiniJinja does not spend time eagerly converting them into values.
489///
490/// Here is a very basic example of how a template can be rendered with a dynamic
491/// context.  Note that the implementation of [`fields`](Self::fields) is optional
492/// for this to work.  It's in fact not used by the engine during rendering but
493/// it is necessary for the [`debug()`](crate::functions::debug) function to be
494/// able to show which values exist in the context.
495///
496/// ```
497/// # fn main() -> Result<(), minijinja::Error> {
498/// # use minijinja::Environment;
499/// use minijinja::value::{Value, StructObject};
500///
501/// pub struct DynamicContext {
502///     magic: i32,
503/// }
504///
505/// impl StructObject for DynamicContext {
506///     fn get_field(&self, field: &str) -> Option<Value> {
507///         match field {
508///             "pid" => Some(Value::from(std::process::id())),
509///             "env" => Some(Value::from_iter(std::env::vars())),
510///             "magic" => Some(Value::from(self.magic)),
511///             _ => None,
512///         }
513///     }
514/// }
515///
516/// # let env = Environment::new();
517/// let tmpl = env.template_from_str("HOME={{ env.HOME }}; PID={{ pid }}; MAGIC={{ magic }}")?;
518/// let ctx = Value::from_struct_object(DynamicContext { magic: 42 });
519/// let rv = tmpl.render(ctx)?;
520/// # Ok(()) }
521/// ```
522///
523/// One thing of note here is that in the above example `env` would be re-created every
524/// time the template needs it.  A better implementation would cache the value after it
525/// was created first.
526pub trait StructObject: Send + Sync {
527    /// Invoked by the engine to get a field of a struct.
528    ///
529    /// Where possible it's a good idea for this to align with the return value
530    /// of [`fields`](Self::fields) but it's not necessary.
531    ///
532    /// If an field does not exist, `None` shall be returned.
533    ///
534    /// A note should be made here on side effects: unlike calling objects or
535    /// calling methods on objects, accessing fields is not supposed to
536    /// have side effects.  Neither does this API get access to the interpreter
537    /// [`State`] nor is there a channel to send out failures as only an option
538    /// can be returned.  If you do plan on doing something in field access
539    /// that is fallible, instead use a method call.
540    fn get_field(&self, name: &str) -> Option<Value>;
541
542    /// If possible returns a static vector of field names.
543    ///
544    /// If fields cannot be statically determined, then this must return `None`
545    /// and [`fields`](Self::fields) should be implemented instead.  If however
546    /// this method is implemented, then [`fields`](Self::fields) should not be
547    /// implemented as the default implementation dispatches to here, or it has
548    /// to be implemented to match the output.
549    fn static_fields(&self) -> Option<&'static [&'static str]> {
550        None
551    }
552
553    /// Returns a vector of field names.
554    ///
555    /// This should be implemented if [`static_fields`](Self::static_fields) cannot
556    /// be implemented due to lifetime restrictions.  The default implementation
557    /// converts the return value of [`static_fields`](Self::static_fields) into
558    /// a compatible format automatically.
559    fn fields(&self) -> Vec<Arc<str>> {
560        self.static_fields()
561            .into_iter()
562            .flat_map(|fields| fields.iter().copied().map(intern))
563            .collect()
564    }
565
566    /// Returns the number of fields.
567    ///
568    /// The default implementation uses [`fields`](Self::fields) and
569    /// [`static_fields`](Self::static_fields) automatically.
570    fn field_count(&self) -> usize {
571        if let Some(fields) = self.static_fields() {
572            fields.len()
573        } else {
574            self.fields().len()
575        }
576    }
577}
578
579impl<T: StructObject> StructObject for Arc<T> {
580    #[inline]
581    fn get_field(&self, name: &str) -> Option<Value> {
582        T::get_field(self, name)
583    }
584
585    #[inline]
586    fn static_fields(&self) -> Option<&'static [&'static str]> {
587        T::static_fields(self)
588    }
589
590    #[inline]
591    fn fields(&self) -> Vec<Arc<str>> {
592        T::fields(self)
593    }
594
595    #[inline]
596    fn field_count(&self) -> usize {
597        T::field_count(self)
598    }
599}
600
601impl<'a, T: StructObject + ?Sized> StructObject for &'a T {
602    #[inline]
603    fn get_field(&self, name: &str) -> Option<Value> {
604        T::get_field(self, name)
605    }
606
607    #[inline]
608    fn static_fields(&self) -> Option<&'static [&'static str]> {
609        T::static_fields(self)
610    }
611
612    #[inline]
613    fn fields(&self) -> Vec<Arc<str>> {
614        T::fields(self)
615    }
616
617    #[inline]
618    fn field_count(&self) -> usize {
619        T::field_count(self)
620    }
621}
622
623#[repr(transparent)]
624pub struct SimpleSeqObject<T>(pub T);
625
626impl<T: SeqObject + 'static> fmt::Display for SimpleSeqObject<T> {
627    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
628        ok!(f.write_str("["));
629        for (idx, val) in (&self.0 as &dyn SeqObject).iter().enumerate() {
630            if idx > 0 {
631                ok!(f.write_str(", "));
632            }
633            ok!(write!(f, "{val:?}"));
634        }
635        f.write_str("]")
636    }
637}
638
639impl<T: SeqObject + 'static> fmt::Debug for SimpleSeqObject<T> {
640    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
641        f.debug_list()
642            .entries((&self.0 as &dyn SeqObject).iter())
643            .finish()
644    }
645}
646
647impl<T: SeqObject + 'static> Object for SimpleSeqObject<T> {
648    fn kind(&self) -> ObjectKind<'_> {
649        ObjectKind::Seq(&self.0)
650    }
651}
652
653#[repr(transparent)]
654pub struct SimpleStructObject<T>(pub T);
655
656impl<T: StructObject + 'static> fmt::Display for SimpleStructObject<T> {
657    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
658        ok!(f.write_str("{"));
659        for (idx, field) in self.0.fields().iter().enumerate() {
660            if idx > 0 {
661                ok!(f.write_str(", "));
662            }
663            let val = self.0.get_field(field).unwrap_or(Value::UNDEFINED);
664            ok!(write!(f, "{field:?}: {val:?}"));
665        }
666        f.write_str("}")
667    }
668}
669
670impl<T: StructObject + 'static> fmt::Debug for SimpleStructObject<T> {
671    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
672        let mut m = f.debug_map();
673        for field in self.0.fields() {
674            let value = self.0.get_field(&field).unwrap_or(Value::UNDEFINED);
675            m.entry(&field, &value);
676        }
677        m.finish()
678    }
679}
680
681impl<T: StructObject + 'static> Object for SimpleStructObject<T> {
682    fn kind(&self) -> ObjectKind<'_> {
683        ObjectKind::Struct(&self.0)
684    }
685}
686
687/// Represents a dynamic iterable.
688///
689/// Iterators need to use interior mutability to function.
690pub trait IteratorObject: Send + Sync {
691    /// Produces the next value from the iterator.
692    fn next_value(&self) -> Option<Value>;
693
694    /// Returns the exact size of the iterator if known.
695    ///
696    /// An iterator must only return the length if it's known and correct.
697    /// The default implementation returns `None`.  If the length is
698    /// provided then `loop.revindex` and `loop.length` will return the
699    /// correct information.
700    fn iterator_len(&self) -> Option<usize> {
701        None
702    }
703}
704
705pub(crate) struct SimpleIteratorObject<I, T>(pub Mutex<I>)
706where
707    I: Iterator<Item = T> + Send + Sync + 'static,
708    T: Into<Value> + 'static;
709
710impl<I, T> fmt::Debug for SimpleIteratorObject<I, T>
711where
712    I: Iterator<Item = T> + Send + Sync + 'static,
713    T: Into<Value> + 'static,
714{
715    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
716        f.debug_tuple("Iterator").finish()
717    }
718}
719
720impl<I, T> fmt::Display for SimpleIteratorObject<I, T>
721where
722    I: Iterator<Item = T> + Send + Sync + 'static,
723    T: Into<Value> + 'static,
724{
725    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
726        write!(f, "<iterator>")
727    }
728}
729
730impl<I, T> Object for SimpleIteratorObject<I, T>
731where
732    I: Iterator<Item = T> + Send + Sync + 'static,
733    T: Into<Value> + 'static,
734{
735    fn kind(&self) -> ObjectKind<'_> {
736        ObjectKind::Iterator(self)
737    }
738}
739
740impl<I, T> IteratorObject for SimpleIteratorObject<I, T>
741where
742    I: Iterator<Item = T> + Send + Sync,
743    T: Into<Value>,
744{
745    fn next_value(&self) -> Option<Value> {
746        self.0.lock().unwrap().next().map(Into::into)
747    }
748
749    fn iterator_len(&self) -> Option<usize> {
750        match self.0.lock().unwrap().size_hint() {
751            (lower, Some(upper)) if lower == upper => Some(lower),
752            _ => None,
753        }
754    }
755}