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}