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}