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