unified_minijinja/value/mod.rs
1//! Provides a dynamic value type abstraction.
2//!
3//! This module gives access to a dynamically typed value which is used by
4//! the template engine during execution.
5//!
6//! For the most part the existence of the value type can be ignored as
7//! MiniJinja will perform the necessary conversions for you. For instance
8//! if you write a filter that converts a string you can directly declare the
9//! filter to take a [`String`](std::string::String). However for some more
10//! advanced use cases it's useful to know that this type exists.
11//!
12//! # Basic Value Conversions
13//!
14//! Values are typically created via the [`From`] trait:
15//!
16//! ```
17//! # use minijinja::value::Value;
18//! let int_value = Value::from(42);
19//! let none_value = Value::from(());
20//! let true_value = Value::from(true);
21//! ```
22//!
23//! Or via the [`FromIterator`] trait which can create sequences or maps:
24//!
25//! ```
26//! # use minijinja::value::Value;
27//! // collection into a sequence
28//! let value: Value = (1..10).into_iter().collect();
29//!
30//! // collection into a map
31//! let value: Value = [("key", "value")].into_iter().collect();
32//! ```
33//!
34//! For certain types of iterators (`Send` + `Sync` + `'static`) it's also
35//! possible to make the value lazily iterate over the value by using the
36//! [`Value::make_iterable`] function instead. Whenever the value requires
37//! iteration, the function is called to create that iterator.
38//!
39//! ```
40//! # use minijinja::value::Value;
41//! let value: Value = Value::make_iterable(|| 1..10);
42//! ```
43//!
44//! To to into the inverse directly the various [`TryFrom`](std::convert::TryFrom)
45//! implementations can be used:
46//!
47//! ```
48//! # use minijinja::value::Value;
49//! use std::convert::TryFrom;
50//! let v = u64::try_from(Value::from(42)).unwrap();
51//! ```
52//!
53//! The special [`Undefined`](Value::UNDEFINED) value also exists but does not
54//! have a rust equivalent. It can be created via the [`UNDEFINED`](Value::UNDEFINED)
55//! constant.
56//!
57//! # Serde Conversions
58//!
59//! MiniJinja will usually however create values via an indirection via [`serde`] when
60//! a template is rendered or an expression is evaluated. This can also be
61//! triggered manually by using the [`Value::from_serializable`] method:
62//!
63//! ```
64//! # use minijinja::value::Value;
65//! let value = Value::from_serializable(&[1, 2, 3]);
66//! ```
67//!
68//! The inverse of that operation is to pass a value directly as serializer to
69//! a type that supports deserialization. This requires the `deserialization`
70//! feature.
71//!
72#![cfg_attr(
73 feature = "deserialization",
74 doc = r"
75```
76# use minijinja::value::Value;
77use serde::Deserialize;
78let value = Value::from(vec![1, 2, 3]);
79let vec = Vec::<i32>::deserialize(value).unwrap();
80```
81"
82)]
83//!
84//! # Value Function Arguments
85//!
86//! [Filters](crate::filters) and [tests](crate::tests) can take values as arguments
87//! but optionally also rust types directly. This conversion for function arguments
88//! is performed by the [`FunctionArgs`] and related traits ([`ArgType`], [`FunctionResult`]).
89//!
90//! # Memory Management
91//!
92//! Values are immutable objects which are internally reference counted which
93//! means they can be copied relatively cheaply. Special care must be taken
94//! so that cycles are not created to avoid causing memory leaks.
95//!
96//! # HTML Escaping
97//!
98//! MiniJinja inherits the general desire to be clever about escaping. For this
99//! purpose a value will (when auto escaping is enabled) always be escaped. To
100//! prevent this behavior the [`safe`](crate::filters::safe) filter can be used
101//! in the template. Outside of templates the [`Value::from_safe_string`] method
102//! can be used to achieve the same result.
103//!
104//! # Dynamic Objects
105//!
106//! Values can also hold "dynamic" objects. These are objects which implement the
107//! [`Object`] trait. These can be used to implement dynamic functionality such
108//! as stateful values and more. Dynamic objects are internally also used to
109//! implement the special `loop` variable, macros and similar things.
110//!
111//! To create a [`Value`] from a dynamic object use [`Value::from_object`],
112//! [`Value::from_dyn_object`]:
113//!
114//! ```rust
115//! # use std::sync::Arc;
116//! # use minijinja::value::{Value, Object, DynObject};
117//! #[derive(Debug)]
118//! struct Foo;
119//!
120//! impl Object for Foo {
121//! /* implementation */
122//! }
123//!
124//! let value = Value::from_object(Foo);
125//! let value = Value::from_dyn_object(Arc::new(Foo));
126//! ```
127
128// this module is based on the content module in insta which in turn is based
129// on the content module in serde::private::ser.
130
131use std::cell::{Cell, RefCell};
132use std::cmp::Ordering;
133use std::collections::BTreeMap;
134use std::fmt;
135use std::hash::{Hash, Hasher};
136use std::sync::{Arc, Mutex};
137
138use serde::ser::{Serialize, Serializer};
139
140use crate::error::{Error, ErrorKind};
141use crate::functions;
142use crate::utils::OnDrop;
143use crate::value::ops::as_f64;
144use crate::value::serialize::transform;
145use crate::vm::State;
146
147pub use crate::value::argtypes::{from_args, ArgType, FunctionArgs, FunctionResult, Kwargs, Rest};
148pub use crate::value::object::{DynObject, Enumerator, Object, ObjectExt, ObjectRepr};
149
150#[macro_use]
151mod type_erase;
152mod argtypes;
153#[cfg(feature = "deserialization")]
154mod deserialize;
155pub(crate) mod merge_object;
156pub(crate) mod namespace_object;
157mod object;
158pub(crate) mod ops;
159mod serialize;
160#[cfg(feature = "key_interning")]
161mod string_interning;
162
163#[cfg(feature = "deserialization")]
164pub use self::deserialize::ViaDeserialize;
165
166// We use in-band signalling to roundtrip some internal values. This is
167// not ideal but unfortunately there is no better system in serde today.
168const VALUE_HANDLE_MARKER: &str = "\x01__minijinja_ValueHandle";
169
170#[cfg(feature = "preserve_order")]
171pub(crate) type ValueMap = indexmap::IndexMap<Value, Value>;
172
173#[cfg(not(feature = "preserve_order"))]
174pub(crate) type ValueMap = std::collections::BTreeMap<Value, Value>;
175
176#[inline(always)]
177pub(crate) fn value_map_with_capacity(capacity: usize) -> ValueMap {
178 #[cfg(not(feature = "preserve_order"))]
179 {
180 let _ = capacity;
181 ValueMap::new()
182 }
183 #[cfg(feature = "preserve_order")]
184 {
185 ValueMap::with_capacity(crate::utils::untrusted_size_hint(capacity))
186 }
187}
188
189thread_local! {
190 static INTERNAL_SERIALIZATION: Cell<bool> = const { Cell::new(false) };
191
192 // This should be an AtomicU64 but sadly 32bit targets do not necessarily have
193 // AtomicU64 available.
194 static LAST_VALUE_HANDLE: Cell<u32> = const { Cell::new(0) };
195 static VALUE_HANDLES: RefCell<BTreeMap<u32, Value>> = RefCell::new(BTreeMap::new());
196}
197
198/// Function that returns true when serialization for [`Value`] is taking place.
199///
200/// MiniJinja internally creates [`Value`] objects from all values passed to the
201/// engine. It does this by going through the regular serde serialization trait.
202/// In some cases users might want to customize the serialization specifically for
203/// MiniJinja because they want to tune the object for the template engine
204/// independently of what is normally serialized to disk.
205///
206/// This function returns `true` when MiniJinja is serializing to [`Value`] and
207/// `false` otherwise. You can call this within your own [`Serialize`]
208/// implementation to change the output format.
209///
210/// This is particularly useful as serialization for MiniJinja does not need to
211/// support deserialization. So it becomes possible to completely change what
212/// gets sent there, even at the cost of serializing something that cannot be
213/// deserialized.
214pub fn serializing_for_value() -> bool {
215 INTERNAL_SERIALIZATION.with(|flag| flag.get())
216}
217
218/// Enables value optimizations.
219///
220/// If `key_interning` is enabled, this turns on that feature, otherwise
221/// it becomes a noop.
222#[inline(always)]
223pub(crate) fn value_optimization() -> impl Drop {
224 #[cfg(feature = "key_interning")]
225 {
226 crate::value::string_interning::use_string_cache()
227 }
228 #[cfg(not(feature = "key_interning"))]
229 {
230 OnDrop::new(|| {})
231 }
232}
233
234fn mark_internal_serialization() -> impl Drop {
235 let old = INTERNAL_SERIALIZATION.with(|flag| {
236 let old = flag.get();
237 flag.set(true);
238 old
239 });
240 OnDrop::new(move || {
241 if !old {
242 INTERNAL_SERIALIZATION.with(|flag| flag.set(false));
243 }
244 })
245}
246
247/// Describes the kind of value.
248#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
249#[non_exhaustive]
250pub enum ValueKind {
251 /// The value is undefined
252 Undefined,
253 /// The value is the none singleton (`()`)
254 None,
255 /// The value is a [`bool`]
256 Bool,
257 /// The value is a number of a supported type.
258 Number,
259 /// The value is a string.
260 String,
261 /// The value is a byte array.
262 Bytes,
263 /// The value is an array of other values.
264 Seq,
265 /// The value is a key/value mapping.
266 Map,
267 /// An iterable
268 Iterable,
269 /// A plain object without specific behavior.
270 Plain,
271 /// This value is invalid. This can happen when a serialization error occurred.
272 Invalid,
273}
274
275impl fmt::Display for ValueKind {
276 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
277 f.write_str(match *self {
278 ValueKind::Undefined => "undefined",
279 ValueKind::None => "none",
280 ValueKind::Bool => "bool",
281 ValueKind::Number => "number",
282 ValueKind::String => "string",
283 ValueKind::Bytes => "bytes",
284 ValueKind::Seq => "sequence",
285 ValueKind::Map => "map",
286 ValueKind::Iterable => "iterator",
287 ValueKind::Plain => "plain object",
288 ValueKind::Invalid => "invalid value",
289 })
290 }
291}
292
293/// Type type of string
294#[derive(Copy, Clone, Debug)]
295pub(crate) enum StringType {
296 Normal,
297 Safe,
298}
299
300/// Wraps an internal copyable value but marks it as packed.
301///
302/// This is used for `i128`/`u128` in the value repr to avoid
303/// the excessive 16 byte alignment.
304#[derive(Copy)]
305#[repr(packed)]
306pub(crate) struct Packed<T: Copy>(pub T);
307
308impl<T: Copy> Clone for Packed<T> {
309 fn clone(&self) -> Self {
310 *self
311 }
312}
313
314#[derive(Clone)]
315pub(crate) enum ValueRepr {
316 Undefined,
317 Bool(bool),
318 U64(u64),
319 I64(i64),
320 F64(f64),
321 None,
322 Invalid(Arc<str>),
323 U128(Packed<u128>),
324 I128(Packed<i128>),
325 // FIXME: Make Cow<'static, str>?
326 String(Arc<str>, StringType),
327 Bytes(Arc<Vec<u8>>),
328 Object(DynObject),
329}
330
331impl fmt::Debug for ValueRepr {
332 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
333 match self {
334 ValueRepr::Undefined => f.write_str("undefined"),
335 ValueRepr::Bool(val) => fmt::Debug::fmt(val, f),
336 ValueRepr::U64(val) => fmt::Debug::fmt(val, f),
337 ValueRepr::I64(val) => fmt::Debug::fmt(val, f),
338 ValueRepr::F64(val) => fmt::Debug::fmt(val, f),
339 ValueRepr::None => f.write_str("none"),
340 ValueRepr::Invalid(ref val) => write!(f, "<invalid value: {}>", val),
341 ValueRepr::U128(val) => fmt::Debug::fmt(&{ val.0 }, f),
342 ValueRepr::I128(val) => fmt::Debug::fmt(&{ val.0 }, f),
343 ValueRepr::String(val, _) => fmt::Debug::fmt(val, f),
344 ValueRepr::Bytes(val) => fmt::Debug::fmt(val, f),
345 ValueRepr::Object(val) => fmt::Debug::fmt(val, f),
346 }
347 }
348}
349
350impl Hash for Value {
351 fn hash<H: Hasher>(&self, state: &mut H) {
352 match &self.0 {
353 ValueRepr::None | ValueRepr::Undefined => 0u8.hash(state),
354 ValueRepr::String(ref s, _) => s.hash(state),
355 ValueRepr::Bool(b) => b.hash(state),
356 ValueRepr::Invalid(s) => s.hash(state),
357 ValueRepr::Bytes(b) => b.hash(state),
358 ValueRepr::Object(d) => d.hash(state),
359 ValueRepr::U64(_)
360 | ValueRepr::I64(_)
361 | ValueRepr::F64(_)
362 | ValueRepr::U128(_)
363 | ValueRepr::I128(_) => {
364 if let Ok(val) = i64::try_from(self.clone()) {
365 val.hash(state)
366 } else {
367 as_f64(self).map(|x| x.to_bits()).hash(state)
368 }
369 }
370 }
371 }
372}
373
374/// Represents a dynamically typed value in the template engine.
375#[derive(Clone)]
376pub struct Value(pub(crate) ValueRepr);
377
378impl PartialEq for Value {
379 fn eq(&self, other: &Self) -> bool {
380 match (&self.0, &other.0) {
381 (ValueRepr::None, ValueRepr::None) => true,
382 (ValueRepr::Undefined, ValueRepr::Undefined) => true,
383 (ValueRepr::String(ref a, _), ValueRepr::String(ref b, _)) => a == b,
384 (ValueRepr::Bytes(a), ValueRepr::Bytes(b)) => a == b,
385 _ => match ops::coerce(self, other) {
386 Some(ops::CoerceResult::F64(a, b)) => a == b,
387 Some(ops::CoerceResult::I128(a, b)) => a == b,
388 Some(ops::CoerceResult::Str(a, b)) => a == b,
389 None => {
390 if let (Some(a), Some(b)) = (self.as_object(), other.as_object()) {
391 if a.repr() != b.repr() {
392 false
393 } else if let (Some(ak), Some(bk)) =
394 (a.try_iter_pairs(), b.try_iter_pairs())
395 {
396 ak.eq(bk)
397 } else {
398 false
399 }
400 } else {
401 false
402 }
403 }
404 },
405 }
406 }
407}
408
409impl Eq for Value {}
410
411impl PartialOrd for Value {
412 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
413 Some(self.cmp(other))
414 }
415}
416
417fn f64_total_cmp(left: f64, right: f64) -> Ordering {
418 // this is taken from f64::total_cmp on newer rust versions
419 let mut left = left.to_bits() as i64;
420 let mut right = right.to_bits() as i64;
421 left ^= (((left >> 63) as u64) >> 1) as i64;
422 right ^= (((right >> 63) as u64) >> 1) as i64;
423 left.cmp(&right)
424}
425
426impl Ord for Value {
427 fn cmp(&self, other: &Self) -> Ordering {
428 let value_ordering = match (&self.0, &other.0) {
429 (ValueRepr::None, ValueRepr::None) => Ordering::Equal,
430 (ValueRepr::Undefined, ValueRepr::Undefined) => Ordering::Equal,
431 (ValueRepr::String(ref a, _), ValueRepr::String(ref b, _)) => a.cmp(b),
432 (ValueRepr::Bytes(a), ValueRepr::Bytes(b)) => a.cmp(b),
433 _ => match ops::coerce(self, other) {
434 Some(ops::CoerceResult::F64(a, b)) => f64_total_cmp(a, b),
435 Some(ops::CoerceResult::I128(a, b)) => a.cmp(&b),
436 Some(ops::CoerceResult::Str(a, b)) => a.cmp(b),
437 None => match (self.kind(), other.kind()) {
438 (ValueKind::Seq, ValueKind::Seq) => match (self.try_iter(), other.try_iter()) {
439 (Ok(a), Ok(b)) => a.cmp(b),
440 _ => self.len().cmp(&other.len()),
441 },
442 (ValueKind::Map, ValueKind::Map) => match (
443 self.as_object().and_then(|x| x.try_iter_pairs()),
444 other.as_object().and_then(|x| x.try_iter_pairs()),
445 ) {
446 (Some(a), Some(b)) => a.cmp(b),
447 _ => self.len().cmp(&other.len()),
448 },
449 _ => Ordering::Equal,
450 },
451 },
452 };
453 value_ordering.then((self.kind() as usize).cmp(&(other.kind() as usize)))
454 }
455}
456
457impl fmt::Debug for Value {
458 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
459 fmt::Debug::fmt(&self.0, f)
460 }
461}
462
463impl fmt::Display for Value {
464 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
465 match &self.0 {
466 ValueRepr::Undefined => Ok(()),
467 ValueRepr::Bool(val) => val.fmt(f),
468 ValueRepr::U64(val) => val.fmt(f),
469 ValueRepr::I64(val) => val.fmt(f),
470 ValueRepr::F64(val) => {
471 if val.is_nan() {
472 f.write_str("NaN")
473 } else if val.is_infinite() {
474 write!(f, "{}inf", if val.is_sign_negative() { "-" } else { "" })
475 } else {
476 let mut num = val.to_string();
477 if !num.contains('.') {
478 num.push_str(".0");
479 }
480 write!(f, "{num}")
481 }
482 }
483 ValueRepr::None => f.write_str("none"),
484 ValueRepr::Invalid(ref val) => write!(f, "<invalid value: {}>", val),
485 ValueRepr::I128(val) => write!(f, "{}", { val.0 }),
486 ValueRepr::String(val, _) => write!(f, "{val}"),
487 ValueRepr::Bytes(val) => write!(f, "{}", String::from_utf8_lossy(val)),
488 ValueRepr::U128(val) => write!(f, "{}", { val.0 }),
489 ValueRepr::Object(x) => write!(f, "{x}"),
490 }
491 }
492}
493
494impl Default for Value {
495 fn default() -> Value {
496 ValueRepr::Undefined.into()
497 }
498}
499
500/// Intern a string.
501///
502/// When the `key_interning` feature is in used, then MiniJinja will attempt to
503/// reuse strings in certain cases. This function can be used to utilize the
504/// same functionality. There is no guarantee that a string will be interned
505/// as there are heuristics involved for it. Additionally the string interning
506/// will only work during the template engine execution (eg: within filters etc.).
507pub fn intern(s: &str) -> Arc<str> {
508 #[cfg(feature = "key_interning")]
509 {
510 crate::value::string_interning::try_intern(s)
511 }
512 #[cfg(not(feature = "key_interning"))]
513 {
514 Arc::from(s.to_string())
515 }
516}
517
518#[allow(clippy::len_without_is_empty)]
519impl Value {
520 /// The undefined value.
521 ///
522 /// This constant exists because the undefined type does not exist in Rust
523 /// and this is the only way to construct it.
524 pub const UNDEFINED: Value = Value(ValueRepr::Undefined);
525
526 /// Creates a value from something that can be serialized.
527 ///
528 /// This is the method that MiniJinja will generally use whenever a serializable
529 /// object is passed to one of the APIs that internally want to create a value.
530 /// For instance this is what [`context!`](crate::context) and
531 /// [`render`](crate::Template::render) will use.
532 ///
533 /// During serialization of the value, [`serializing_for_value`] will return
534 /// `true` which makes it possible to customize serialization for MiniJinja.
535 /// For more information see [`serializing_for_value`].
536 ///
537 /// ```
538 /// # use minijinja::value::Value;
539 /// let val = Value::from_serializable(&vec![1, 2, 3]);
540 /// ```
541 ///
542 /// This method does not fail but it might return a value that is not valid. Such
543 /// values will when operated on fail in the template engine in most situations.
544 /// This for instance can happen if the underlying implementation of [`Serialize`]
545 /// fails. There are also cases where invalid objects are silently hidden in the
546 /// engine today. This is for instance the case for when keys are used in hash maps
547 /// that the engine cannot deal with. Invalid values are considered an implementation
548 /// detail. There is currently no API to validate a value.
549 ///
550 /// If the `deserialization` feature is enabled then the inverse of this method
551 /// is to use the [`Value`] type as serializer. You can pass a value into the
552 /// [`deserialize`](serde::Deserialize::deserialize) method of a type that supports
553 /// serde deserialization.
554 pub fn from_serializable<T: Serialize>(value: &T) -> Value {
555 let _serialization_guard = mark_internal_serialization();
556 let _optimization_guard = value_optimization();
557 transform(value)
558 }
559
560 /// Creates a value from a safe string.
561 ///
562 /// A safe string is one that will bypass auto escaping. For instance if you
563 /// want to have the template engine render some HTML without the user having to
564 /// supply the `|safe` filter, you can use a value of this type instead.
565 ///
566 /// ```
567 /// # use minijinja::value::Value;
568 /// let val = Value::from_safe_string("<em>note</em>".into());
569 /// ```
570 pub fn from_safe_string(value: String) -> Value {
571 ValueRepr::String(Arc::from(value), StringType::Safe).into()
572 }
573
574 /// Creates a value from a dynamic object.
575 ///
576 /// For more information see [`Object`].
577 ///
578 /// ```rust
579 /// # use minijinja::value::{Value, Object};
580 /// use std::fmt;
581 ///
582 /// #[derive(Debug)]
583 /// struct Thing {
584 /// id: usize,
585 /// }
586 ///
587 /// impl Object for Thing {}
588 ///
589 /// let val = Value::from_object(Thing { id: 42 });
590 /// ```
591 pub fn from_object<T: Object + Send + Sync + 'static>(value: T) -> Value {
592 Value::from(ValueRepr::Object(DynObject::new(Arc::new(value))))
593 }
594
595 /// Like [`from_object`](Self::from_object) but for type erased dynamic objects.
596 pub fn from_dyn_object<T: Into<DynObject>>(value: T) -> Value {
597 Value::from(ValueRepr::Object(value.into()))
598 }
599
600 /// Creates a value that is an iterable.
601 ///
602 /// The function is invoked to create a new iterator every time the value is
603 /// iterated over.
604 ///
605 /// ```
606 /// # use minijinja::value::Value;
607 /// let val = Value::make_iterable(|| 0..10);
608 /// ```
609 ///
610 /// Iterators that implement [`ExactSizeIterator`] or have a matching lower and upper
611 /// bound on the [`Iterator::size_hint`] report a known `loop.length`. Iterators that
612 /// do not fulfill these requirements will not. The same is true for `revindex` and
613 /// similar properties.
614 pub fn make_iterable<I, T, F>(maker: F) -> Value
615 where
616 I: Iterator<Item = T> + Send + Sync + 'static,
617 T: Into<Value> + Send + Sync + 'static,
618 F: Fn() -> I + Send + Sync + 'static,
619 {
620 Value::make_object_iterable((), move |_| Box::new(maker().map(Into::into)))
621 }
622
623 /// Creates an iterable that iterates over the given value.
624 ///
625 /// This is similar to [`make_iterable`](Self::make_iterable) but it takes an extra
626 /// reference to a value it can borrow out from. It's a bit less generic in that it
627 /// needs to return a boxed iterator of values directly.
628 ///
629 /// ```rust
630 /// # use minijinja::value::Value;
631 /// let val = Value::make_object_iterable(vec![1, 2, 3], |vec| {
632 /// Box::new(vec.iter().copied().map(Value::from))
633 /// });
634 /// assert_eq!(val.to_string(), "[1, 2, 3]");
635 /// ````
636 pub fn make_object_iterable<T, F>(object: T, maker: F) -> Value
637 where
638 T: Send + Sync + 'static,
639 F: for<'a> Fn(&'a T) -> Box<dyn Iterator<Item = Value> + Send + Sync + 'a>
640 + Send
641 + Sync
642 + 'static,
643 {
644 struct Iterable<T, F> {
645 maker: F,
646 object: T,
647 }
648
649 impl<T, F> fmt::Debug for Iterable<T, F> {
650 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
651 f.debug_struct("<iterator>").finish()
652 }
653 }
654
655 impl<T, F> Object for Iterable<T, F>
656 where
657 T: Send + Sync + 'static,
658 F: for<'a> Fn(&'a T) -> Box<dyn Iterator<Item = Value> + Send + Sync + 'a>
659 + Send
660 + Sync
661 + 'static,
662 {
663 fn repr(self: &Arc<Self>) -> ObjectRepr {
664 ObjectRepr::Iterable
665 }
666
667 fn enumerate(self: &Arc<Self>) -> Enumerator {
668 struct Iter {
669 iter: Box<dyn Iterator<Item = Value> + Send + Sync + 'static>,
670 _object: DynObject,
671 }
672
673 impl Iterator for Iter {
674 type Item = Value;
675
676 fn next(&mut self) -> Option<Self::Item> {
677 self.iter.next()
678 }
679
680 fn size_hint(&self) -> (usize, Option<usize>) {
681 self.iter.size_hint()
682 }
683 }
684
685 // SAFETY: this is safe because the object is kept alive by the iter
686 let iter = unsafe { std::mem::transmute((self.maker)(&self.object)) };
687 let _object = DynObject::new(self.clone());
688 Enumerator::Iter(Box::new(Iter { iter, _object }))
689 }
690 }
691
692 Value::from_object(Iterable { maker, object })
693 }
694
695 /// Creates a value from a one-shot iterator.
696 ///
697 /// This takes an iterator (yielding values that can be turned into a [`Value`])
698 /// and wraps it in a way that it turns into an iterable value. From the view of
699 /// the template this can be iterated over exactly once for the most part once
700 /// exhausted.
701 ///
702 /// Such iterators are strongly recommended against in the general sense due to
703 /// their surprising behavior, but they can be useful for more advanced use
704 /// cases where data should be streamed into the template as it becomes available.
705 ///
706 /// Such iterators never have any size hints.
707 ///
708 /// ```
709 /// # use minijinja::value::Value;
710 /// let val = Value::make_one_shot_iterator(0..10);
711 /// ```
712 ///
713 /// Attempting to iterate over it a second time will not yield any more items.
714 pub fn make_one_shot_iterator<I, T>(iter: I) -> Value
715 where
716 I: Iterator<Item = T> + Send + Sync + 'static,
717 T: Into<Value> + Send + Sync + 'static,
718 {
719 let iter = Arc::new(Mutex::new(iter.fuse()));
720 Value::make_iterable(move || {
721 let iter = iter.clone();
722 std::iter::from_fn(move || iter.lock().unwrap().next())
723 })
724 }
725
726 /// Creates a callable value from a function.
727 ///
728 /// ```
729 /// # use minijinja::value::Value;
730 /// let pow = Value::from_function(|a: u32| a * a);
731 /// ```
732 pub fn from_function<F, Rv, Args>(f: F) -> Value
733 where
734 // the crazy bounds here exist to enable borrowing in closures
735 F: functions::Function<Rv, Args>
736 + for<'a> functions::Function<Rv, <Args as FunctionArgs<'a>>::Output>,
737 Rv: FunctionResult,
738 Args: for<'a> FunctionArgs<'a>,
739 {
740 functions::BoxedFunction::new(f).to_value()
741 }
742
743 /// Returns the kind of the value.
744 ///
745 /// This can be used to determine what's in the value before trying to
746 /// perform operations on it.
747 pub fn kind(&self) -> ValueKind {
748 match self.0 {
749 ValueRepr::Undefined => ValueKind::Undefined,
750 ValueRepr::Bool(_) => ValueKind::Bool,
751 ValueRepr::U64(_) | ValueRepr::I64(_) | ValueRepr::F64(_) => ValueKind::Number,
752 ValueRepr::None => ValueKind::None,
753 ValueRepr::I128(_) => ValueKind::Number,
754 ValueRepr::String(..) => ValueKind::String,
755 ValueRepr::Bytes(_) => ValueKind::Bytes,
756 ValueRepr::U128(_) => ValueKind::Number,
757 ValueRepr::Invalid(_) => ValueKind::Invalid,
758 ValueRepr::Object(ref obj) => match obj.repr() {
759 ObjectRepr::Map => ValueKind::Map,
760 ObjectRepr::Seq => ValueKind::Seq,
761 ObjectRepr::Iterable => ValueKind::Iterable,
762 ObjectRepr::Plain => ValueKind::Plain,
763 },
764 }
765 }
766
767 /// Returns `true` if the value is a number.
768 ///
769 /// To convert a value into a primitive number, use [`TryFrom`] or [`TryInto`].
770 pub fn is_number(&self) -> bool {
771 matches!(
772 self.0,
773 ValueRepr::U64(_)
774 | ValueRepr::I64(_)
775 | ValueRepr::F64(_)
776 | ValueRepr::I128(_)
777 | ValueRepr::U128(_)
778 )
779 }
780
781 /// Returns `true` if the map represents keyword arguments.
782 pub fn is_kwargs(&self) -> bool {
783 Kwargs::extract(self).is_some()
784 }
785
786 /// Is this value true?
787 pub fn is_true(&self) -> bool {
788 match self.0 {
789 ValueRepr::Bool(val) => val,
790 ValueRepr::U64(x) => x != 0,
791 ValueRepr::U128(x) => x.0 != 0,
792 ValueRepr::I64(x) => x != 0,
793 ValueRepr::I128(x) => x.0 != 0,
794 ValueRepr::F64(x) => x != 0.0,
795 ValueRepr::String(ref x, _) => !x.is_empty(),
796 ValueRepr::Bytes(ref x) => !x.is_empty(),
797 ValueRepr::None | ValueRepr::Undefined | ValueRepr::Invalid(_) => false,
798 ValueRepr::Object(ref x) => !x.is_empty(),
799 }
800 }
801
802 /// Returns `true` if this value is safe.
803 pub fn is_safe(&self) -> bool {
804 matches!(&self.0, ValueRepr::String(_, StringType::Safe))
805 }
806
807 /// Returns `true` if this value is undefined.
808 pub fn is_undefined(&self) -> bool {
809 matches!(&self.0, ValueRepr::Undefined)
810 }
811
812 /// Returns `true` if this value is none.
813 pub fn is_none(&self) -> bool {
814 matches!(&self.0, ValueRepr::None)
815 }
816
817 /// If the value is a string, return it.
818 pub fn to_str(&self) -> Option<Arc<str>> {
819 match &self.0 {
820 ValueRepr::String(ref s, _) => Some(s.clone()),
821 _ => None,
822 }
823 }
824
825 /// If the value is a string, return it.
826 pub fn as_str(&self) -> Option<&str> {
827 match &self.0 {
828 ValueRepr::String(ref s, _) => Some(s as &str),
829 _ => None,
830 }
831 }
832
833 /// If this is an i64 return it
834 pub fn as_usize(&self) -> Option<usize> {
835 usize::try_from(self.clone()).ok()
836 }
837
838 /// If this is an i64 return it
839 pub fn as_i64(&self) -> Option<i64> {
840 i64::try_from(self.clone()).ok()
841 }
842
843 /// Returns the bytes of this value if they exist.
844 pub fn as_bytes(&self) -> Option<&[u8]> {
845 match &self.0 {
846 ValueRepr::String(ref s, _) => Some(s.as_bytes()),
847 ValueRepr::Bytes(ref b) => Some(&b[..]),
848 _ => None,
849 }
850 }
851
852 /// If the value is an object, it's returned as [`Object`].
853 pub fn as_object(&self) -> Option<DynObject> {
854 match self.0 {
855 ValueRepr::Object(ref dy) => Some(dy.clone()),
856 _ => None,
857 }
858 }
859
860 /// Returns the length of the contained value.
861 ///
862 /// Values without a length will return `None`.
863 ///
864 /// ```
865 /// # use minijinja::value::Value;
866 /// let seq = Value::from(vec![1, 2, 3, 4]);
867 /// assert_eq!(seq.len(), Some(4));
868 /// ```
869 pub fn len(&self) -> Option<usize> {
870 match self.0 {
871 ValueRepr::String(ref s, _) => Some(s.chars().count()),
872 ValueRepr::Object(ref dy) => dy.len(),
873 _ => None,
874 }
875 }
876
877 /// Looks up an attribute by attribute name.
878 ///
879 /// This this returns [`UNDEFINED`](Self::UNDEFINED) when an invalid key is
880 /// resolved. An error is returned if the value does not contain an object
881 /// that has attributes.
882 ///
883 /// ```
884 /// # use minijinja::value::Value;
885 /// # fn test() -> Result<(), minijinja::Error> {
886 /// let ctx = minijinja::context! {
887 /// foo => "Foo"
888 /// };
889 /// let value = ctx.get_attr("foo")?;
890 /// assert_eq!(value.to_string(), "Foo");
891 /// # Ok(()) }
892 /// ```
893 pub fn get_attr(&self, key: &str) -> Result<Value, Error> {
894 let value = match self.0 {
895 ValueRepr::Undefined => return Err(Error::from(ErrorKind::UndefinedError)),
896 ValueRepr::Object(ref dy) => dy.get_value(&Value::from(key)),
897 _ => None,
898 };
899
900 Ok(value.unwrap_or(Value::UNDEFINED))
901 }
902
903 /// Alternative lookup strategy without error handling exclusively for context
904 /// resolution.
905 ///
906 /// The main difference is that the return value will be `None` if the value is
907 /// unable to look up the key rather than returning `Undefined` and errors will
908 /// also not be created.
909 pub(crate) fn get_attr_fast(&self, key: &str) -> Option<Value> {
910 match self.0 {
911 ValueRepr::Object(ref dy) => dy.get_value(&Value::from(key)),
912 _ => None,
913 }
914 }
915
916 /// Looks up an index of the value.
917 ///
918 /// This is a shortcut for [`get_item`](Self::get_item).
919 ///
920 /// ```
921 /// # use minijinja::value::Value;
922 /// let seq = Value::from(vec![0u32, 1, 2]);
923 /// let value = seq.get_item_by_index(1).unwrap();
924 /// assert_eq!(value.try_into().ok(), Some(1));
925 /// ```
926 pub fn get_item_by_index(&self, idx: usize) -> Result<Value, Error> {
927 self.get_item(&Value(ValueRepr::U64(idx as _)))
928 }
929
930 /// Looks up an item (or attribute) by key.
931 ///
932 /// This is similar to [`get_attr`](Self::get_attr) but instead of using
933 /// a string key this can be any key. For instance this can be used to
934 /// index into sequences. Like [`get_attr`](Self::get_attr) this returns
935 /// [`UNDEFINED`](Self::UNDEFINED) when an invalid key is looked up.
936 ///
937 /// ```
938 /// # use minijinja::value::Value;
939 /// let ctx = minijinja::context! {
940 /// foo => "Foo",
941 /// };
942 /// let value = ctx.get_item(&Value::from("foo")).unwrap();
943 /// assert_eq!(value.to_string(), "Foo");
944 /// ```
945 pub fn get_item(&self, key: &Value) -> Result<Value, Error> {
946 if let ValueRepr::Undefined = self.0 {
947 Err(Error::from(ErrorKind::UndefinedError))
948 } else {
949 Ok(self.get_item_opt(key).unwrap_or(Value::UNDEFINED))
950 }
951 }
952
953 /// Iterates over the value.
954 ///
955 /// Depending on the [`kind`](Self::kind) of the value the iterator
956 /// has a different behavior.
957 ///
958 /// * [`ValueKind::Map`]: the iterator yields the keys of the map.
959 /// * [`ValueKind::Seq`]: the iterator yields the items in the sequence.
960 /// * [`ValueKind::None`] / [`ValueKind::Undefined`]: the iterator is empty.
961 ///
962 /// ```
963 /// # use minijinja::value::Value;
964 /// # fn test() -> Result<(), minijinja::Error> {
965 /// let value = Value::from({
966 /// let mut m = std::collections::BTreeMap::new();
967 /// m.insert("foo", 42);
968 /// m.insert("bar", 23);
969 /// m
970 /// });
971 /// for key in value.try_iter()? {
972 /// let value = value.get_item(&key)?;
973 /// println!("{} = {}", key, value);
974 /// }
975 /// # Ok(()) }
976 /// ```
977 pub fn try_iter(&self) -> Result<ValueIter, Error> {
978 match self.0 {
979 ValueRepr::None | ValueRepr::Undefined => Some(ValueIterImpl::Empty),
980 ValueRepr::String(ref s, _) => {
981 Some(ValueIterImpl::Chars(0, s.chars().count(), Arc::clone(s)))
982 }
983 ValueRepr::Object(ref obj) => obj.try_iter().map(ValueIterImpl::Dyn),
984 _ => None,
985 }
986 .map(|imp| ValueIter { imp })
987 .ok_or_else(|| {
988 Error::new(
989 ErrorKind::InvalidOperation,
990 format!("{} is not iterable", self.kind()),
991 )
992 })
993 }
994
995 /// Returns a reversed view of this value.
996 ///
997 /// This is implemented for the following types with the following behaviors:
998 ///
999 /// * undefined or none: value returned unchanged.
1000 /// * string and bytes: returns a reversed version of that value
1001 /// * iterables: returns a reversed version of the iterable. If the iterable is not
1002 /// reversable itself, it consumes it and then reverses it.
1003 pub fn reverse(&self) -> Result<Value, Error> {
1004 match self.0 {
1005 ValueRepr::Undefined | ValueRepr::None => Some(self.clone()),
1006 ValueRepr::String(ref s, _) => Some(Value::from(s.chars().rev().collect::<String>())),
1007 ValueRepr::Bytes(ref b) => {
1008 Some(Value::from(b.iter().rev().copied().collect::<Vec<_>>()))
1009 }
1010 ValueRepr::Object(ref o) => match o.enumerate() {
1011 Enumerator::NonEnumerable => None,
1012 Enumerator::Empty => Some(Value::make_iterable(|| None::<Value>.into_iter())),
1013 Enumerator::Seq(l) => {
1014 let self_clone = o.clone();
1015 Some(Value::make_iterable(move || {
1016 let self_clone = self_clone.clone();
1017 (0..l).rev().map(move |idx| {
1018 self_clone.get_value(&Value::from(idx)).unwrap_or_default()
1019 })
1020 }))
1021 }
1022 Enumerator::Iter(iter) => {
1023 let mut v = iter.collect::<Vec<_>>();
1024 v.reverse();
1025 Some(Value::make_object_iterable(v, move |v| {
1026 Box::new(v.iter().cloned())
1027 }))
1028 }
1029 Enumerator::RevIter(rev_iter) => {
1030 let for_restart = self.clone();
1031 let iter = Mutex::new(Some(rev_iter));
1032 Some(Value::make_iterable(move || {
1033 if let Some(iter) = iter.lock().unwrap().take() {
1034 Box::new(iter) as Box<dyn Iterator<Item = Value> + Send + Sync>
1035 } else if let Ok(iter) = for_restart.reverse().and_then(|x| x.try_iter()) {
1036 Box::new(iter) as Box<dyn Iterator<Item = Value> + Send + Sync>
1037 } else {
1038 Box::new(None.into_iter())
1039 as Box<dyn Iterator<Item = Value> + Send + Sync>
1040 }
1041 }))
1042 }
1043 Enumerator::Str(s) => Some(Value::make_iterable(move || s.iter().rev().copied())),
1044 Enumerator::Values(mut v) => {
1045 v.reverse();
1046 Some(Value::make_object_iterable(v, move |v| {
1047 Box::new(v.iter().cloned())
1048 }))
1049 }
1050 },
1051 _ => None,
1052 }
1053 .ok_or_else(|| {
1054 Error::new(
1055 ErrorKind::InvalidOperation,
1056 format!("cannot reverse values of type {}", self.kind()),
1057 )
1058 })
1059 }
1060
1061 /// Returns some reference to the boxed object if it is of type `T`, or None if it isn’t.
1062 ///
1063 /// This is basically the "reverse" of [`from_object`](Self::from_object),
1064 /// [`from_object`](Self::from_object) and
1065 /// [`from_object`](Self::from_object). It's also a shortcut for
1066 /// [`downcast_ref`](trait.Object.html#method.downcast_ref) on the return
1067 /// value of [`as_object`](Self::as_object).
1068 ///
1069 /// # Example
1070 ///
1071 /// ```rust
1072 /// # use minijinja::value::{Value, Object};
1073 /// use std::fmt;
1074 ///
1075 /// #[derive(Debug)]
1076 /// struct Thing {
1077 /// id: usize,
1078 /// }
1079 ///
1080 /// impl Object for Thing {}
1081 ///
1082 /// let x_value = Value::from_object(Thing { id: 42 });
1083 /// let thing = x_value.downcast_object_ref::<Thing>().unwrap();
1084 /// assert_eq!(thing.id, 42);
1085 /// ```
1086 pub fn downcast_object_ref<T: 'static>(&self) -> Option<&T> {
1087 match self.0 {
1088 ValueRepr::Object(ref o) => o.downcast_ref(),
1089 _ => None,
1090 }
1091 }
1092
1093 /// Like [`downcast_object_ref`](Self::downcast_object_ref) but returns
1094 /// the actual object.
1095 pub fn downcast_object<T: 'static>(&self) -> Option<Arc<T>> {
1096 match self.0 {
1097 ValueRepr::Object(ref o) => o.downcast(),
1098 _ => None,
1099 }
1100 }
1101
1102 pub(crate) fn get_item_opt(&self, key: &Value) -> Option<Value> {
1103 fn index(value: &Value, len: impl Fn() -> Option<usize>) -> Option<usize> {
1104 match value.as_i64().and_then(|v| isize::try_from(v).ok()) {
1105 Some(i) if i < 0 => some!(len()).checked_sub(i.unsigned_abs()),
1106 Some(i) => Some(i as usize),
1107 None => None,
1108 }
1109 }
1110
1111 match self.0 {
1112 ValueRepr::Object(ref dy) => match dy.repr() {
1113 ObjectRepr::Map | ObjectRepr::Plain | ObjectRepr::Iterable => dy.get_value(key),
1114 ObjectRepr::Seq => {
1115 let idx = index(key, || dy.len()).map(Value::from);
1116 dy.get_value(idx.as_ref().unwrap_or(key))
1117 }
1118 },
1119 ValueRepr::String(ref s, _) => {
1120 let idx = some!(index(key, || Some(s.chars().count())));
1121 s.chars().nth(idx).map(Value::from)
1122 }
1123 _ => None,
1124 }
1125 }
1126
1127 /// Calls the value directly.
1128 ///
1129 /// If the value holds a function or macro, this invokes it. Note that in
1130 /// MiniJinja there is a separate namespace for methods on objects and callable
1131 /// items. To call methods (which should be a rather rare occurrence) you
1132 /// have to use [`call_method`](Self::call_method).
1133 ///
1134 /// The `args` slice is for the arguments of the function call. To pass
1135 /// keyword arguments use the [`Kwargs`] type.
1136 ///
1137 /// Usually the state is already available when it's useful to call this method,
1138 /// but when it's not available you can get a fresh template state straight
1139 /// from the [`Template`](crate::Template) via [`new_state`](crate::Template::new_state).
1140 ///
1141 /// ```
1142 /// # use minijinja::{Environment, value::{Value, Kwargs}};
1143 /// # let mut env = Environment::new();
1144 /// # env.add_template("foo", "").unwrap();
1145 /// # let tmpl = env.get_template("foo").unwrap();
1146 /// # let state = tmpl.new_state(); let state = &state;
1147 /// let func = Value::from_function(|v: i64, kwargs: Kwargs| {
1148 /// v * kwargs.get::<i64>("mult").unwrap_or(1)
1149 /// });
1150 /// let rv = func.call(
1151 /// state,
1152 /// &[
1153 /// Value::from(42),
1154 /// Value::from(Kwargs::from_iter([("mult", Value::from(2))])),
1155 /// ],
1156 /// ).unwrap();
1157 /// assert_eq!(rv, Value::from(84));
1158 /// ```
1159 ///
1160 /// With the [`args!`](crate::args) macro creating an argument slice is
1161 /// simplified:
1162 ///
1163 /// ```
1164 /// # use minijinja::{Environment, args, value::{Value, Kwargs}};
1165 /// # let mut env = Environment::new();
1166 /// # env.add_template("foo", "").unwrap();
1167 /// # let tmpl = env.get_template("foo").unwrap();
1168 /// # let state = tmpl.new_state(); let state = &state;
1169 /// let func = Value::from_function(|v: i64, kwargs: Kwargs| {
1170 /// v * kwargs.get::<i64>("mult").unwrap_or(1)
1171 /// });
1172 /// let rv = func.call(state, args!(42, mult => 2)).unwrap();
1173 /// assert_eq!(rv, Value::from(84));
1174 /// ```
1175 pub fn call(&self, state: &State, args: &[Value]) -> Result<Value, Error> {
1176 if let ValueRepr::Object(ref dy) = self.0 {
1177 dy.call(state, args)
1178 } else {
1179 Err(Error::new(
1180 ErrorKind::InvalidOperation,
1181 format!("value of type {} is not callable", self.kind()),
1182 ))
1183 }
1184 }
1185
1186 /// Calls a method on the value.
1187 ///
1188 /// The name of the method is `name`, the arguments passed are in the `args`
1189 /// slice.
1190 pub fn call_method(&self, state: &State, name: &str, args: &[Value]) -> Result<Value, Error> {
1191 match self._call_method(state, name, args) {
1192 Ok(rv) => Ok(rv),
1193 Err(err) => {
1194 if err.kind() == ErrorKind::UnknownMethod {
1195 if let Some(ref callback) = state.env().unknown_method_callback {
1196 return callback(state, self, name, args);
1197 }
1198 }
1199 Err(err)
1200 }
1201 }
1202 }
1203
1204 fn _call_method(&self, state: &State, name: &str, args: &[Value]) -> Result<Value, Error> {
1205 if let Some(object) = self.as_object() {
1206 object.call_method(state, name, args)
1207 } else {
1208 Err(Error::new(
1209 ErrorKind::UnknownMethod,
1210 format!("object has no method named {name}"),
1211 ))
1212 }
1213 }
1214
1215 #[cfg(feature = "builtins")]
1216 pub(crate) fn get_path(&self, path: &str) -> Result<Value, Error> {
1217 let mut rv = self.clone();
1218 for part in path.split('.') {
1219 if let Ok(num) = part.parse::<usize>() {
1220 rv = ok!(rv.get_item_by_index(num));
1221 } else {
1222 rv = ok!(rv.get_attr(part));
1223 }
1224 }
1225 Ok(rv)
1226 }
1227}
1228
1229impl Serialize for Value {
1230 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1231 where
1232 S: Serializer,
1233 {
1234 // enable round tripping of values
1235 if serializing_for_value() {
1236 let handle = LAST_VALUE_HANDLE.with(|x| {
1237 // we are okay with overflowing the handle here because these values only
1238 // live for a very short period of time and it's not likely that you run out
1239 // of an entire u32 worth of handles in a single serialization operation.
1240 // This lets us stick the handle into a unit variant in the serde data model.
1241 let rv = x.get().wrapping_add(1);
1242 x.set(rv);
1243 rv
1244 });
1245 VALUE_HANDLES.with(|handles| handles.borrow_mut().insert(handle, self.clone()));
1246 return serializer.serialize_unit_variant(
1247 VALUE_HANDLE_MARKER,
1248 handle,
1249 VALUE_HANDLE_MARKER,
1250 );
1251 }
1252
1253 match self.0 {
1254 ValueRepr::Bool(b) => serializer.serialize_bool(b),
1255 ValueRepr::U64(u) => serializer.serialize_u64(u),
1256 ValueRepr::I64(i) => serializer.serialize_i64(i),
1257 ValueRepr::F64(f) => serializer.serialize_f64(f),
1258 ValueRepr::None | ValueRepr::Undefined | ValueRepr::Invalid(_) => {
1259 serializer.serialize_unit()
1260 }
1261 ValueRepr::U128(u) => serializer.serialize_u128(u.0),
1262 ValueRepr::I128(i) => serializer.serialize_i128(i.0),
1263 ValueRepr::String(ref s, _) => serializer.serialize_str(s),
1264 ValueRepr::Bytes(ref b) => serializer.serialize_bytes(b),
1265 ValueRepr::Object(ref o) => match o.repr() {
1266 ObjectRepr::Plain => serializer.serialize_str(&o.to_string()),
1267 ObjectRepr::Seq | ObjectRepr::Iterable => {
1268 use serde::ser::SerializeSeq;
1269 let mut seq = ok!(serializer.serialize_seq(o.len()));
1270 if let Some(iter) = o.try_iter() {
1271 for item in iter {
1272 ok!(seq.serialize_element(&item));
1273 }
1274 }
1275
1276 seq.end()
1277 }
1278 ObjectRepr::Map => {
1279 use serde::ser::SerializeMap;
1280 let mut map = ok!(serializer.serialize_map(None));
1281 if let Some(iter) = o.try_iter_pairs() {
1282 for (key, value) in iter {
1283 ok!(map.serialize_entry(&key, &value));
1284 }
1285 }
1286
1287 map.end()
1288 }
1289 },
1290 }
1291 }
1292}
1293
1294/// Utility to iterate over values.
1295pub struct ValueIter {
1296 imp: ValueIterImpl,
1297}
1298
1299impl Iterator for ValueIter {
1300 type Item = Value;
1301
1302 fn next(&mut self) -> Option<Self::Item> {
1303 match &mut self.imp {
1304 ValueIterImpl::Empty => None,
1305 ValueIterImpl::Chars(offset, len, ref s) => {
1306 (s as &str)[*offset..].chars().next().map(|c| {
1307 *offset += c.len_utf8();
1308 *len -= 1;
1309 Value::from(c)
1310 })
1311 }
1312 ValueIterImpl::Dyn(iter) => iter.next(),
1313 }
1314 }
1315
1316 fn size_hint(&self) -> (usize, Option<usize>) {
1317 match self.imp {
1318 ValueIterImpl::Empty => (0, Some(0)),
1319 ValueIterImpl::Chars(_, len, _) => (0, Some(len)),
1320 ValueIterImpl::Dyn(ref iter) => iter.size_hint(),
1321 }
1322 }
1323}
1324
1325impl fmt::Debug for ValueIter {
1326 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1327 f.debug_struct("ValueIterator").finish()
1328 }
1329}
1330
1331enum ValueIterImpl {
1332 Empty,
1333 Chars(usize, usize, Arc<str>),
1334 Dyn(Box<dyn Iterator<Item = Value> + Send + Sync>),
1335}
1336
1337#[cfg(test)]
1338mod tests {
1339 use super::*;
1340
1341 use similar_asserts::assert_eq;
1342
1343 #[test]
1344 fn test_dynamic_object_roundtrip() {
1345 use std::sync::atomic::{self, AtomicUsize};
1346
1347 #[derive(Debug, Clone)]
1348 struct X(Arc<AtomicUsize>);
1349
1350 impl Object for X {
1351 fn get_value(self: &Arc<Self>, key: &Value) -> Option<Value> {
1352 match key.as_str()? {
1353 "value" => Some(Value::from(self.0.load(atomic::Ordering::Relaxed))),
1354 _ => None,
1355 }
1356 }
1357
1358 fn enumerate(self: &Arc<Self>) -> Enumerator {
1359 Enumerator::Str(&["value"])
1360 }
1361
1362 fn render(self: &Arc<Self>, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1363 write!(f, "{}", self.0.load(atomic::Ordering::Relaxed))
1364 }
1365 }
1366
1367 let x = Arc::new(X(Default::default()));
1368 let x_value = Value::from_dyn_object(x.clone());
1369 x.0.fetch_add(42, atomic::Ordering::Relaxed);
1370 let x_clone = Value::from_serializable(&x_value);
1371 x.0.fetch_add(23, atomic::Ordering::Relaxed);
1372
1373 assert_eq!(x_value.to_string(), "65");
1374 assert_eq!(x_clone.to_string(), "65");
1375 }
1376
1377 #[test]
1378 fn test_string_char() {
1379 let val = Value::from('a');
1380 assert_eq!(char::try_from(val).unwrap(), 'a');
1381 let val = Value::from("a");
1382 assert_eq!(char::try_from(val).unwrap(), 'a');
1383 let val = Value::from("wat");
1384 assert!(char::try_from(val).is_err());
1385 }
1386
1387 #[test]
1388 #[cfg(target_pointer_width = "64")]
1389 fn test_sizes() {
1390 assert_eq!(std::mem::size_of::<Value>(), 24);
1391 }
1392}