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`]. However for some more advanced use cases it's
10//! 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 std::collections::BTreeMap;
18//! # use minijinja::value::Value;
19//! let int_value = Value::from(42);
20//! let none_value = Value::from(());
21//! let true_value = Value::from(true);
22//! let map = Value::from({
23//! let mut m = BTreeMap::new();
24//! m.insert("foo", 1);
25//! m.insert("bar", 2);
26//! m
27//! });
28//! ```
29//!
30//! Or via the [`FromIterator`] trait which can create sequences or maps. When
31//! given a tuple it creates maps, otherwise it makes a sequence.
32//!
33//! ```
34//! # use minijinja::value::Value;
35//! // collection into a sequence
36//! let value: Value = (1..10).into_iter().collect();
37//!
38//! // collection into a map
39//! let value: Value = [("key", "value")].into_iter().collect();
40//! ```
41//!
42//! For certain types of iterators (`Send` + `Sync` + `'static`) it's also
43//! possible to make the value lazily iterate over the value by using the
44//! [`Value::make_iterable`] function instead. Whenever the value requires
45//! iteration, the function is called to create that iterator.
46//!
47//! ```
48//! # use minijinja::value::Value;
49//! let value: Value = Value::make_iterable(|| 1..10);
50//! ```
51//!
52//! To to into the inverse directly the various [`TryFrom`]
53//! implementations can be used:
54//!
55//! ```
56//! # use minijinja::value::Value;
57//! use std::convert::TryFrom;
58//! let v = u64::try_from(Value::from(42)).unwrap();
59//! ```
60//!
61//! The special [`Undefined`](Value::UNDEFINED) value also exists but does not
62//! have a rust equivalent. It can be created via the [`UNDEFINED`](Value::UNDEFINED)
63//! constant.
64//!
65//! # Collections
66//!
67//! The standard library's collection types such as
68//! [`HashMap`](std::collections::HashMap), [`Vec`] and various others from the
69//! collections module are implemented are objects. There is a cavet here which is
70//! that maps can only have string or [`Value`] as key. The values in the collections
71//! are lazily converted into value when accessed or iterated over. These types can
72//! be constructed either from [`Value::from`] or [`Value::from_object`]. Because the
73//! types are boxed unchanged, you can also downcast them.
74//!
75//! ```rust
76//! # use minijinja::Value;
77//! let vec = Value::from(vec![1i32, 2, 3, 4]);
78//! let vec_ref = vec.downcast_object_ref::<Vec<i32>>().unwrap();
79//! assert_eq!(vec_ref, &vec![1, 2, 3, 4]);
80//! ```
81//!
82//! **Caveat:** for convenience reasons maps with `&str` keys can be stored. The keys
83//! however are converted into `Arc<str>`.
84//!
85//! # Serde Conversions
86//!
87//! MiniJinja will usually however create values via an indirection via [`serde`] when
88//! a template is rendered or an expression is evaluated. This can also be
89//! triggered manually by using the [`Value::from_serialize`] method:
90//!
91//! ```
92//! # use minijinja::value::Value;
93//! let value = Value::from_serialize(&[1, 2, 3]);
94//! ```
95//!
96//! The inverse of that operation is to pass a value directly as serializer to
97//! a type that supports deserialization. This requires the `deserialization`
98//! feature.
99//!
100#![cfg_attr(
101 feature = "deserialization",
102 doc = r"
103```
104# use minijinja::value::Value;
105use serde::Deserialize;
106let value = Value::from(vec![1, 2, 3]);
107let vec = Vec::<i32>::deserialize(value).unwrap();
108```
109"
110)]
111//!
112//! # Value Function Arguments
113//!
114//! [Filters](crate::filters) and [tests](crate::tests) can take values as arguments
115//! but optionally also rust types directly. This conversion for function arguments
116//! is performed by the [`FunctionArgs`] and related traits ([`ArgType`], [`FunctionResult`]).
117//!
118//! # Memory Management
119//!
120//! Values are immutable objects which are internally reference counted which
121//! means they can be copied relatively cheaply. Special care must be taken
122//! so that cycles are not created to avoid causing memory leaks.
123//!
124//! # HTML Escaping
125//!
126//! MiniJinja inherits the general desire to be clever about escaping. For this
127//! purpose a value will (when auto escaping is enabled) always be escaped. To
128//! prevent this behavior the [`safe`](crate::filters::safe) filter can be used
129//! in the template. Outside of templates the [`Value::from_safe_string`] method
130//! can be used to achieve the same result.
131//!
132//! # Dynamic Objects
133//!
134//! Values can also hold "dynamic" objects. These are objects which implement the
135//! [`Object`] trait. These can be used to implement dynamic functionality such
136//! as stateful values and more. Dynamic objects are internally also used to
137//! implement the special `loop` variable, macros and similar things.
138//!
139//! To create a [`Value`] from a dynamic object use [`Value::from_object`],
140//! [`Value::from_dyn_object`]:
141//!
142//! ```rust
143//! # use std::sync::Arc;
144//! # use minijinja::value::{Value, Object, DynObject};
145//! #[derive(Debug)]
146//! struct Foo;
147//!
148//! impl Object for Foo {
149//! /* implementation */
150//! }
151//!
152//! let value = Value::from_object(Foo);
153//! let value = Value::from_dyn_object(Arc::new(Foo));
154//! ```
155//!
156//! # Invalid Values
157//!
158//! MiniJinja knows the concept of an "invalid value". These are rare in practice
159//! and should not be used, but they are needed in some situations. An invalid value
160//! looks like a value but working with that value in the context of the engine will
161//! fail in most situations. In principle an invalid value is a value that holds an
162//! error internally. It's created with [`From`]:
163//!
164//! ```
165//! use minijinja::{Value, Error, ErrorKind};
166//! let error = Error::new(ErrorKind::InvalidOperation, "failed to generate an item");
167//! let invalid_value = Value::from(error);
168//! ```
169//!
170//! Invalid values are typically encountered in the following situations:
171//!
172//! - serialization fails with an error: this is the case when a value is crated
173//! via [`Value::from_serialize`] and the underlying [`Serialize`] implementation
174//! fails with an error.
175//! - fallible iteration: there might be situations where an iterator cannot indicate
176//! failure ahead of iteration and must abort. In that case the only option an
177//! iterator in MiniJinja has is to create an invalid value.
178//!
179//! It's generally recommende to ignore the existence of invalid objects and let them
180//! fail naturally as they are encountered.
181//!
182//! # Notes on Bytes and Strings
183//!
184//! Usually one would pass strings to templates as Jinja is entirely based on string
185//! rendering. However there are situations where it can be useful to pass bytes instead.
186//! As such MiniJinja allows a value type to carry bytes even though there is no syntax
187//! within the template language to create a byte literal.
188//!
189//! When rendering bytes as strings, MiniJinja will attempt to interpret them as
190//! lossy utf-8. This is a bit different to Jinja2 which in Python 3 stopped
191//! rendering byte strings as strings. This is an intentional change that was
192//! deemed acceptable given how infrequently bytes are used but how relatively
193//! commonly bytes are often holding "almost utf-8" in templates. Most
194//! conversions to strings also will do almost the same. The debug rendering of
195//! bytes however is different and bytes are not iterable. Like strings however
196//! they can be sliced and indexed, but they will be sliced by bytes and not by
197//! characters.
198
199// this module is based on the content module in insta which in turn is based
200// on the content module in serde::private::ser.
201
202use core::str;
203use std::cell::{Cell, RefCell};
204use std::cmp::Ordering;
205use std::collections::BTreeMap;
206use std::fmt;
207use std::hash::{Hash, Hasher};
208use std::sync::{Arc, Mutex};
209
210use serde::ser::{Serialize, SerializeTupleStruct, Serializer};
211
212use crate::error::{Error, ErrorKind};
213use crate::functions;
214use crate::utils::OnDrop;
215use crate::value::ops::as_f64;
216use crate::value::serialize::transform;
217use crate::vm::State;
218
219pub use crate::value::argtypes::{from_args, ArgType, FunctionArgs, FunctionResult, Kwargs, Rest};
220pub use crate::value::merge_object::merge_maps;
221pub use crate::value::object::{DynObject, Enumerator, Object, ObjectExt, ObjectRepr};
222
223#[macro_use]
224mod type_erase;
225mod argtypes;
226#[cfg(feature = "deserialization")]
227mod deserialize;
228pub(crate) mod merge_object;
229pub(crate) mod namespace_object;
230mod object;
231pub(crate) mod ops;
232mod serialize;
233
234#[cfg(feature = "deserialization")]
235pub use self::deserialize::ViaDeserialize;
236
237// We use in-band signalling to roundtrip some internal values. This is
238// not ideal but unfortunately there is no better system in serde today.
239const VALUE_HANDLE_MARKER: &str = "\x01__minijinja_ValueHandle";
240
241#[cfg(feature = "preserve_order")]
242pub(crate) type ValueMap = indexmap::IndexMap<Value, Value>;
243
244#[cfg(not(feature = "preserve_order"))]
245pub(crate) type ValueMap = std::collections::BTreeMap<Value, Value>;
246
247#[inline(always)]
248pub(crate) fn value_map_with_capacity(capacity: usize) -> ValueMap {
249 #[cfg(not(feature = "preserve_order"))]
250 {
251 let _ = capacity;
252 ValueMap::new()
253 }
254 #[cfg(feature = "preserve_order")]
255 {
256 ValueMap::with_capacity(crate::utils::untrusted_size_hint(capacity))
257 }
258}
259
260thread_local! {
261 static INTERNAL_SERIALIZATION: Cell<bool> = const { Cell::new(false) };
262
263 // This should be an AtomicU64 but sadly 32bit targets do not necessarily have
264 // AtomicU64 available.
265 static LAST_VALUE_HANDLE: Cell<u32> = const { Cell::new(0) };
266 static VALUE_HANDLES: RefCell<BTreeMap<u32, Value>> = const { RefCell::new(BTreeMap::new()) };
267}
268
269/// Function that returns true when serialization for [`Value`] is taking place.
270///
271/// MiniJinja internally creates [`Value`] objects from all values passed to the
272/// engine. It does this by going through the regular serde serialization trait.
273/// In some cases users might want to customize the serialization specifically for
274/// MiniJinja because they want to tune the object for the template engine
275/// independently of what is normally serialized to disk.
276///
277/// This function returns `true` when MiniJinja is serializing to [`Value`] and
278/// `false` otherwise. You can call this within your own [`Serialize`]
279/// implementation to change the output format.
280///
281/// This is particularly useful as serialization for MiniJinja does not need to
282/// support deserialization. So it becomes possible to completely change what
283/// gets sent there, even at the cost of serializing something that cannot be
284/// deserialized.
285pub fn serializing_for_value() -> bool {
286 INTERNAL_SERIALIZATION.with(|flag| flag.get())
287}
288
289fn mark_internal_serialization() -> impl Drop {
290 let old = INTERNAL_SERIALIZATION.with(|flag| {
291 let old = flag.get();
292 flag.set(true);
293 old
294 });
295 OnDrop::new(move || {
296 if !old {
297 INTERNAL_SERIALIZATION.with(|flag| flag.set(false));
298 }
299 })
300}
301
302/// Describes the kind of value.
303#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
304#[non_exhaustive]
305pub enum ValueKind {
306 /// The value is undefined
307 Undefined,
308 /// The value is the none singleton (`()`)
309 None,
310 /// The value is a [`bool`]
311 Bool,
312 /// The value is a number of a supported type.
313 Number,
314 /// The value is a string.
315 String,
316 /// The value is a byte array.
317 Bytes,
318 /// The value is an array of other values.
319 Seq,
320 /// The value is a key/value mapping.
321 Map,
322 /// An iterable
323 Iterable,
324 /// A plain object without specific behavior.
325 Plain,
326 /// This value is invalid (holds an error).
327 ///
328 /// This can happen when a serialization error occurred or the engine
329 /// encountered a failure in a place where an error can otherwise not
330 /// be produced. Interacting with such values in the context of the
331 /// template evaluation process will attempt to propagate the error.
332 Invalid,
333}
334
335impl fmt::Display for ValueKind {
336 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
337 f.write_str(match *self {
338 ValueKind::Undefined => "undefined",
339 ValueKind::None => "none",
340 ValueKind::Bool => "bool",
341 ValueKind::Number => "number",
342 ValueKind::String => "string",
343 ValueKind::Bytes => "bytes",
344 ValueKind::Seq => "sequence",
345 ValueKind::Map => "map",
346 ValueKind::Iterable => "iterator",
347 ValueKind::Plain => "plain object",
348 ValueKind::Invalid => "invalid value",
349 })
350 }
351}
352
353/// Type type of string
354#[derive(Copy, Clone, Debug)]
355pub(crate) enum StringType {
356 Normal,
357 Safe,
358}
359
360/// Type type of undefined
361#[derive(Copy, Clone, Debug)]
362pub(crate) enum UndefinedType {
363 Default,
364 Silent,
365}
366
367/// Wraps an internal copyable value but marks it as packed.
368///
369/// This is used for `i128`/`u128` in the value repr to avoid
370/// the excessive 16 byte alignment.
371#[derive(Copy, Debug)]
372#[cfg_attr(feature = "unstable_machinery_serde", derive(serde::Serialize))]
373#[repr(packed)]
374pub(crate) struct Packed<T: Copy>(pub T);
375
376impl<T: Copy> Clone for Packed<T> {
377 fn clone(&self) -> Self {
378 *self
379 }
380}
381
382/// Max size of a small str.
383///
384/// Logic: Value is 24 bytes. 1 byte is for the discriminant. One byte is
385/// needed for the small str length.
386const SMALL_STR_CAP: usize = 22;
387
388/// Helper to store string data inline.
389#[derive(Clone)]
390pub(crate) struct SmallStr {
391 len: u8,
392 buf: [u8; SMALL_STR_CAP],
393}
394
395impl SmallStr {
396 pub fn try_new(s: &str) -> Option<SmallStr> {
397 let len = s.len();
398 if len <= SMALL_STR_CAP {
399 let mut buf = [0u8; SMALL_STR_CAP];
400 buf[..len].copy_from_slice(s.as_bytes());
401 Some(SmallStr {
402 len: len as u8,
403 buf,
404 })
405 } else {
406 None
407 }
408 }
409
410 pub fn as_str(&self) -> &str {
411 // SAFETY: This is safe because we only place well-formed utf-8 strings
412 unsafe { std::str::from_utf8_unchecked(&self.buf[..self.len as usize]) }
413 }
414
415 pub fn is_empty(&self) -> bool {
416 self.len == 0
417 }
418}
419
420#[derive(Clone)]
421pub(crate) enum ValueRepr {
422 None,
423 Undefined(UndefinedType),
424 Bool(bool),
425 U64(u64),
426 I64(i64),
427 F64(f64),
428 Invalid(Arc<Error>),
429 U128(Packed<u128>),
430 I128(Packed<i128>),
431 String(Arc<str>, StringType),
432 SmallStr(SmallStr),
433 Bytes(Arc<Vec<u8>>),
434 Object(DynObject),
435}
436
437impl fmt::Debug for ValueRepr {
438 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
439 match *self {
440 ValueRepr::Undefined(_) => f.write_str("undefined"),
441 ValueRepr::Bool(ref val) => fmt::Debug::fmt(val, f),
442 ValueRepr::U64(ref val) => fmt::Debug::fmt(val, f),
443 ValueRepr::I64(ref val) => fmt::Debug::fmt(val, f),
444 ValueRepr::F64(ref val) => fmt::Debug::fmt(val, f),
445 ValueRepr::None => f.write_str("none"),
446 ValueRepr::Invalid(ref val) => write!(f, "<invalid value: {}>", val),
447 ValueRepr::U128(val) => fmt::Debug::fmt(&{ val.0 }, f),
448 ValueRepr::I128(val) => fmt::Debug::fmt(&{ val.0 }, f),
449 ValueRepr::String(ref val, _) => fmt::Debug::fmt(val, f),
450 ValueRepr::SmallStr(ref val) => fmt::Debug::fmt(val.as_str(), f),
451 ValueRepr::Bytes(ref val) => {
452 write!(f, "b'")?;
453 for &b in val.iter() {
454 if b == b'"' {
455 write!(f, "\"")?
456 } else {
457 write!(f, "{}", b.escape_ascii())?;
458 }
459 }
460 write!(f, "'")
461 }
462 ValueRepr::Object(ref val) => val.render(f),
463 }
464 }
465}
466
467impl Hash for Value {
468 fn hash<H: Hasher>(&self, state: &mut H) {
469 match self.0 {
470 ValueRepr::None | ValueRepr::Undefined(_) => 0u8.hash(state),
471 ValueRepr::String(ref s, _) => s.hash(state),
472 ValueRepr::SmallStr(ref s) => s.as_str().hash(state),
473 ValueRepr::Bool(b) => b.hash(state),
474 ValueRepr::Invalid(ref e) => (e.kind(), e.detail()).hash(state),
475 ValueRepr::Bytes(ref b) => b.hash(state),
476 ValueRepr::Object(ref d) => d.hash(state),
477 ValueRepr::U64(_)
478 | ValueRepr::I64(_)
479 | ValueRepr::F64(_)
480 | ValueRepr::U128(_)
481 | ValueRepr::I128(_) => {
482 if let Ok(val) = i64::try_from(self.clone()) {
483 val.hash(state)
484 } else {
485 as_f64(self, true).map(|x| x.to_bits()).hash(state)
486 }
487 }
488 }
489 }
490}
491
492/// Represents a dynamically typed value in the template engine.
493#[derive(Clone)]
494pub struct Value(pub(crate) ValueRepr);
495
496impl PartialEq for Value {
497 fn eq(&self, other: &Self) -> bool {
498 match (&self.0, &other.0) {
499 (&ValueRepr::None, &ValueRepr::None) => true,
500 (&ValueRepr::Undefined(_), &ValueRepr::Undefined(_)) => true,
501 (&ValueRepr::String(ref a, _), &ValueRepr::String(ref b, _)) => a == b,
502 (&ValueRepr::SmallStr(ref a), &ValueRepr::SmallStr(ref b)) => a.as_str() == b.as_str(),
503 (&ValueRepr::Bytes(ref a), &ValueRepr::Bytes(ref b)) => a == b,
504 _ => match ops::coerce(self, other, false) {
505 Some(ops::CoerceResult::F64(a, b)) => a == b,
506 Some(ops::CoerceResult::I128(a, b)) => a == b,
507 Some(ops::CoerceResult::Str(a, b)) => a == b,
508 None => {
509 if let (Some(a), Some(b)) = (self.as_object(), other.as_object()) {
510 if a.is_same_object(b) {
511 return true;
512 } else if a.is_same_object_type(b) {
513 if let Some(rv) = a.custom_cmp(b) {
514 return rv == Ordering::Equal;
515 }
516 }
517 match (a.repr(), b.repr()) {
518 (ObjectRepr::Map, ObjectRepr::Map) => {
519 // only if we have known lengths can we compare the enumerators
520 // ahead of time. This function has a fallback for when a
521 // map has an unknown length. That's generally a bad idea, but
522 // it makes sense supporting regardless as silent failures are
523 // not a lot of fun.
524 let mut need_length_fallback = true;
525 if let (Some(a_len), Some(b_len)) =
526 (a.enumerator_len(), b.enumerator_len())
527 {
528 if a_len != b_len {
529 return false;
530 }
531 need_length_fallback = false;
532 }
533 let mut a_count = 0;
534 if !a.try_iter_pairs().is_some_and(|mut ak| {
535 ak.all(|(k, v1)| {
536 a_count += 1;
537 b.get_value(&k) == Some(v1)
538 })
539 }) {
540 return false;
541 }
542 if !need_length_fallback {
543 true
544 } else {
545 a_count == b.try_iter().map_or(0, |x| x.count())
546 }
547 }
548 (
549 ObjectRepr::Seq | ObjectRepr::Iterable,
550 ObjectRepr::Seq | ObjectRepr::Iterable,
551 ) => {
552 if let (Some(ak), Some(bk)) = (a.try_iter(), b.try_iter()) {
553 ak.eq(bk)
554 } else {
555 false
556 }
557 }
558 // terrible fallback for plain objects
559 (ObjectRepr::Plain, ObjectRepr::Plain) => {
560 a.to_string() == b.to_string()
561 }
562 // should not happen
563 (_, _) => false,
564 }
565 } else {
566 false
567 }
568 }
569 },
570 }
571 }
572}
573
574impl Eq for Value {}
575
576impl PartialOrd for Value {
577 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
578 Some(self.cmp(other))
579 }
580}
581
582fn f64_total_cmp(left: f64, right: f64) -> Ordering {
583 // this is taken from f64::total_cmp on newer rust versions
584 let mut left = left.to_bits() as i64;
585 let mut right = right.to_bits() as i64;
586 left ^= (((left >> 63) as u64) >> 1) as i64;
587 right ^= (((right >> 63) as u64) >> 1) as i64;
588 left.cmp(&right)
589}
590
591impl Ord for Value {
592 fn cmp(&self, other: &Self) -> Ordering {
593 let kind_ordering = self.kind().cmp(&other.kind());
594 if matches!(kind_ordering, Ordering::Less | Ordering::Greater) {
595 return kind_ordering;
596 }
597 match (&self.0, &other.0) {
598 (&ValueRepr::None, &ValueRepr::None) => Ordering::Equal,
599 (&ValueRepr::Undefined(_), &ValueRepr::Undefined(_)) => Ordering::Equal,
600 (&ValueRepr::String(ref a, _), &ValueRepr::String(ref b, _)) => a.cmp(b),
601 (&ValueRepr::SmallStr(ref a), &ValueRepr::SmallStr(ref b)) => {
602 a.as_str().cmp(b.as_str())
603 }
604 (&ValueRepr::Bytes(ref a), &ValueRepr::Bytes(ref b)) => a.cmp(b),
605 _ => match ops::coerce(self, other, false) {
606 Some(ops::CoerceResult::F64(a, b)) => f64_total_cmp(a, b),
607 Some(ops::CoerceResult::I128(a, b)) => a.cmp(&b),
608 Some(ops::CoerceResult::Str(a, b)) => a.cmp(b),
609 None => {
610 let a = self.as_object().unwrap();
611 let b = other.as_object().unwrap();
612
613 if a.is_same_object(b) {
614 Ordering::Equal
615 } else {
616 // if there is a custom comparison, run it.
617 if a.is_same_object_type(b) {
618 if let Some(rv) = a.custom_cmp(b) {
619 return rv;
620 }
621 }
622 match (a.repr(), b.repr()) {
623 (ObjectRepr::Map, ObjectRepr::Map) => {
624 // This is not really correct. Because the keys can be in arbitrary
625 // order this could just sort really weirdly as a result. However
626 // we don't want to pay the cost of actually sorting the keys for
627 // ordering so we just accept this for now.
628 match (a.try_iter_pairs(), b.try_iter_pairs()) {
629 (Some(a), Some(b)) => a.cmp(b),
630 _ => unreachable!(),
631 }
632 }
633 (
634 ObjectRepr::Seq | ObjectRepr::Iterable,
635 ObjectRepr::Seq | ObjectRepr::Iterable,
636 ) => match (a.try_iter(), b.try_iter()) {
637 (Some(a), Some(b)) => a.cmp(b),
638 _ => unreachable!(),
639 },
640 // terrible fallback for plain objects
641 (ObjectRepr::Plain, ObjectRepr::Plain) => {
642 a.to_string().cmp(&b.to_string())
643 }
644 // should not happen
645 (_, _) => unreachable!(),
646 }
647 }
648 }
649 },
650 }
651 }
652}
653
654impl fmt::Debug for Value {
655 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
656 fmt::Debug::fmt(&self.0, f)
657 }
658}
659
660impl fmt::Display for Value {
661 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
662 match self.0 {
663 ValueRepr::Undefined(_) => Ok(()),
664 ValueRepr::Bool(val) => val.fmt(f),
665 ValueRepr::U64(val) => val.fmt(f),
666 ValueRepr::I64(val) => val.fmt(f),
667 ValueRepr::F64(val) => {
668 if val.is_nan() {
669 f.write_str("NaN")
670 } else if val.is_infinite() {
671 write!(f, "{}inf", if val.is_sign_negative() { "-" } else { "" })
672 } else {
673 let mut num = val.to_string();
674 if !num.contains('.') {
675 num.push_str(".0");
676 }
677 write!(f, "{num}")
678 }
679 }
680 ValueRepr::None => f.write_str("none"),
681 ValueRepr::Invalid(ref val) => write!(f, "<invalid value: {}>", val),
682 ValueRepr::I128(val) => write!(f, "{}", { val.0 }),
683 ValueRepr::String(ref val, _) => write!(f, "{val}"),
684 ValueRepr::SmallStr(ref val) => write!(f, "{}", val.as_str()),
685 ValueRepr::Bytes(ref val) => write!(f, "{}", String::from_utf8_lossy(val)),
686 ValueRepr::U128(val) => write!(f, "{}", { val.0 }),
687 ValueRepr::Object(ref x) => write!(f, "{x}"),
688 }
689 }
690}
691
692impl Default for Value {
693 fn default() -> Value {
694 ValueRepr::Undefined(UndefinedType::Default).into()
695 }
696}
697
698#[doc(hidden)]
699#[deprecated = "This function no longer has an effect. Use Arc::from directly."]
700pub fn intern(s: &str) -> Arc<str> {
701 Arc::from(s.to_string())
702}
703
704#[allow(clippy::len_without_is_empty)]
705impl Value {
706 /// The undefined value.
707 ///
708 /// This constant exists because the undefined type does not exist in Rust
709 /// and this is the only way to construct it.
710 pub const UNDEFINED: Value = Value(ValueRepr::Undefined(UndefinedType::Default));
711
712 /// Creates a value from something that can be serialized.
713 ///
714 /// This is the method that MiniJinja will generally use whenever a serializable
715 /// object is passed to one of the APIs that internally want to create a value.
716 /// For instance this is what [`context!`](crate::context) and
717 /// [`render`](crate::Template::render) will use.
718 ///
719 /// During serialization of the value, [`serializing_for_value`] will return
720 /// `true` which makes it possible to customize serialization for MiniJinja.
721 /// For more information see [`serializing_for_value`].
722 ///
723 /// ```
724 /// # use minijinja::value::Value;
725 /// let val = Value::from_serialize(&vec![1, 2, 3]);
726 /// ```
727 ///
728 /// This method does not fail but it might return a value that is not valid. Such
729 /// values will when operated on fail in the template engine in most situations.
730 /// This for instance can happen if the underlying implementation of [`Serialize`]
731 /// fails. There are also cases where invalid objects are silently hidden in the
732 /// engine today. This is for instance the case for when keys are used in hash maps
733 /// that the engine cannot deal with. Invalid values are considered an implementation
734 /// detail. There is currently no API to validate a value.
735 ///
736 /// If the `deserialization` feature is enabled then the inverse of this method
737 /// is to use the [`Value`] type as serializer. You can pass a value into the
738 /// [`deserialize`](serde::Deserialize::deserialize) method of a type that supports
739 /// serde deserialization.
740 pub fn from_serialize<T: Serialize>(value: T) -> Value {
741 let _serialization_guard = mark_internal_serialization();
742 transform(value)
743 }
744
745 /// Extracts a contained error.
746 ///
747 /// An invalid value carres an error internally and will reveal that error
748 /// at a later point when iteracted with. This is used to carry
749 /// serialization errors or failures that happen when the engine otherwise
750 /// assumes an infallible operation such as iteration.
751 pub(crate) fn validate(self) -> Result<Value, Error> {
752 if let ValueRepr::Invalid(err) = self.0 {
753 // Today the API implies tghat errors are `Clone`, but we don't want to expose
754 // this as a functionality (yet?).
755 Err(Arc::try_unwrap(err).unwrap_or_else(|arc| (*arc).internal_clone()))
756 } else {
757 Ok(self)
758 }
759 }
760
761 /// Creates a value from a safe string.
762 ///
763 /// A safe string is one that will bypass auto escaping. For instance if you
764 /// want to have the template engine render some HTML without the user having to
765 /// supply the `|safe` filter, you can use a value of this type instead.
766 ///
767 /// ```
768 /// # use minijinja::value::Value;
769 /// let val = Value::from_safe_string("<em>note</em>".into());
770 /// ```
771 pub fn from_safe_string(value: String) -> Value {
772 ValueRepr::String(Arc::from(value), StringType::Safe).into()
773 }
774
775 /// Creates a value from a byte vector.
776 ///
777 /// MiniJinja can hold on to bytes and has some limited built-in support for
778 /// working with them. They are non iterable and not particularly useful
779 /// in the context of templates. When they are stringified, they are assumed
780 /// to contain UTF-8 and will be treated as such. They become more useful
781 /// when a filter can do something with them (eg: base64 encode them etc.).
782 ///
783 /// This method exists so that a value can be constructed as creating a
784 /// value from a `Vec<u8>` would normally just create a sequence.
785 pub fn from_bytes(value: Vec<u8>) -> Value {
786 ValueRepr::Bytes(value.into()).into()
787 }
788
789 /// Creates a value from a dynamic object.
790 ///
791 /// For more information see [`Object`].
792 ///
793 /// ```rust
794 /// # use minijinja::value::{Value, Object};
795 /// use std::fmt;
796 ///
797 /// #[derive(Debug)]
798 /// struct Thing {
799 /// id: usize,
800 /// }
801 ///
802 /// impl Object for Thing {}
803 ///
804 /// let val = Value::from_object(Thing { id: 42 });
805 /// ```
806 pub fn from_object<T: Object + Send + Sync + 'static>(value: T) -> Value {
807 Value::from(ValueRepr::Object(DynObject::new(Arc::new(value))))
808 }
809
810 /// Like [`from_object`](Self::from_object) but for type erased dynamic objects.
811 ///
812 /// This especially useful if you have an object that has an `Arc<T>` to another
813 /// child object that you want to return as a `Arc<T>` turns into a [`DynObject`]
814 /// automatically.
815 ///
816 /// ```rust
817 /// # use std::sync::Arc;
818 /// # use minijinja::value::{Value, Object, Enumerator};
819 /// #[derive(Debug)]
820 /// pub struct HttpConfig {
821 /// port: usize,
822 /// }
823 ///
824 /// #[derive(Debug)]
825 /// struct Config {
826 /// http: Arc<HttpConfig>,
827 /// }
828 ///
829 /// impl Object for HttpConfig {
830 /// fn enumerate(self: &Arc<Self>) -> Enumerator {
831 /// Enumerator::Str(&["port"])
832 /// }
833 ///
834 /// fn get_value(self: &Arc<Self>, key: &Value) -> Option<Value> {
835 /// match key.as_str()? {
836 /// "port" => Some(Value::from(self.port)),
837 /// _ => None,
838 /// }
839 /// }
840 /// }
841 ///
842 /// impl Object for Config {
843 /// fn enumerate(self: &Arc<Self>) -> Enumerator {
844 /// Enumerator::Str(&["http"])
845 /// }
846 ///
847 /// fn get_value(self: &Arc<Self>, key: &Value) -> Option<Value> {
848 /// match key.as_str()? {
849 /// "http" => Some(Value::from_dyn_object(self.http.clone())),
850 /// _ => None
851 /// }
852 /// }
853 /// }
854 /// ```
855 pub fn from_dyn_object<T: Into<DynObject>>(value: T) -> Value {
856 Value::from(ValueRepr::Object(value.into()))
857 }
858
859 /// Creates a value that is an iterable.
860 ///
861 /// The function is invoked to create a new iterator every time the value is
862 /// iterated over.
863 ///
864 /// ```
865 /// # use minijinja::value::Value;
866 /// let val = Value::make_iterable(|| 0..10);
867 /// ```
868 ///
869 /// Iterators that implement [`ExactSizeIterator`] or have a matching lower and upper
870 /// bound on the [`Iterator::size_hint`] report a known `loop.length`. Iterators that
871 /// do not fulfill these requirements will not. The same is true for `revindex` and
872 /// similar properties.
873 pub fn make_iterable<I, T, F>(maker: F) -> Value
874 where
875 I: Iterator<Item = T> + Send + Sync + 'static,
876 T: Into<Value> + Send + Sync + 'static,
877 F: Fn() -> I + Send + Sync + 'static,
878 {
879 Value::make_object_iterable((), move |_| Box::new(maker().map(Into::into)))
880 }
881
882 /// Creates an iterable that iterates over the given value.
883 ///
884 /// This is similar to [`make_iterable`](Self::make_iterable) but it takes an extra
885 /// reference to a value it can borrow out from. It's a bit less generic in that it
886 /// needs to return a boxed iterator of values directly.
887 ///
888 /// ```rust
889 /// # use minijinja::value::Value;
890 /// let val = Value::make_object_iterable(vec![1, 2, 3], |vec| {
891 /// Box::new(vec.iter().copied().map(Value::from))
892 /// });
893 /// assert_eq!(val.to_string(), "[1, 2, 3]");
894 /// ````
895 pub fn make_object_iterable<T, F>(object: T, maker: F) -> Value
896 where
897 T: Send + Sync + 'static,
898 F: for<'a> Fn(&'a T) -> Box<dyn Iterator<Item = Value> + Send + Sync + 'a>
899 + Send
900 + Sync
901 + 'static,
902 {
903 struct Iterable<T, F> {
904 maker: F,
905 object: T,
906 }
907
908 impl<T, F> fmt::Debug for Iterable<T, F> {
909 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
910 f.debug_struct("<iterator>").finish()
911 }
912 }
913
914 impl<T, F> Object for Iterable<T, F>
915 where
916 T: Send + Sync + 'static,
917 F: for<'a> Fn(&'a T) -> Box<dyn Iterator<Item = Value> + Send + Sync + 'a>
918 + Send
919 + Sync
920 + 'static,
921 {
922 fn repr(self: &Arc<Self>) -> ObjectRepr {
923 ObjectRepr::Iterable
924 }
925
926 fn enumerate(self: &Arc<Self>) -> Enumerator {
927 mapped_enumerator(self, |this| (this.maker)(&this.object))
928 }
929 }
930
931 Value::from_object(Iterable { maker, object })
932 }
933
934 /// Creates an object projection onto a map.
935 ///
936 /// This is similar to [`make_object_iterable`](Self::make_object_iterable) but
937 /// it creates a map rather than an iterable. To accomplish this, it also
938 /// requires two callbacks. One for enumeration, and one for looking up
939 /// attributes.
940 ///
941 /// # Example
942 ///
943 /// ```
944 /// use std::collections::HashMap;
945 /// use std::sync::Arc;
946 /// use minijinja::value::{Value, Object, ObjectExt, Enumerator};
947 ///
948 /// #[derive(Debug)]
949 /// struct Element {
950 /// tag: String,
951 /// attrs: HashMap<String, String>,
952 /// }
953 ///
954 /// impl Object for Element {
955 /// fn get_value(self: &Arc<Self>, key: &Value) -> Option<Value> {
956 /// match key.as_str()? {
957 /// "tag" => Some(Value::from(&self.tag)),
958 /// "attrs" => Some(Value::make_object_map(
959 /// self.clone(),
960 /// |this| Box::new(this.attrs.keys().map(Value::from)),
961 /// |this, key| this.attrs.get(key.as_str()?).map(Value::from),
962 /// )),
963 /// _ => None
964 /// }
965 /// }
966 ///
967 /// fn enumerate(self: &Arc<Self>) -> Enumerator {
968 /// Enumerator::Str(&["tag", "attrs"])
969 /// }
970 /// }
971 /// ```
972 pub fn make_object_map<T, E, A>(object: T, enumerate_fn: E, attr_fn: A) -> Value
973 where
974 T: Send + Sync + 'static,
975 E: for<'a> Fn(&'a T) -> Box<dyn Iterator<Item = Value> + Send + Sync + 'a>
976 + Send
977 + Sync
978 + 'static,
979 A: Fn(&T, &Value) -> Option<Value> + Send + Sync + 'static,
980 {
981 struct ProxyMapObject<T, E, A> {
982 enumerate_fn: E,
983 attr_fn: A,
984 object: T,
985 }
986
987 impl<T, E, A> fmt::Debug for ProxyMapObject<T, E, A> {
988 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
989 f.debug_struct("<map-object>").finish()
990 }
991 }
992
993 impl<T, E, A> Object for ProxyMapObject<T, E, A>
994 where
995 T: Send + Sync + 'static,
996 E: for<'a> Fn(&'a T) -> Box<dyn Iterator<Item = Value> + Send + Sync + 'a>
997 + Send
998 + Sync
999 + 'static,
1000 A: Fn(&T, &Value) -> Option<Value> + Send + Sync + 'static,
1001 {
1002 #[inline]
1003 fn get_value(self: &Arc<Self>, key: &Value) -> Option<Value> {
1004 (self.attr_fn)(&self.object, key)
1005 }
1006
1007 #[inline]
1008 fn enumerate(self: &Arc<Self>) -> Enumerator {
1009 mapped_enumerator(self, |this| (this.enumerate_fn)(&this.object))
1010 }
1011 }
1012
1013 Value::from_object(ProxyMapObject {
1014 enumerate_fn,
1015 attr_fn,
1016 object,
1017 })
1018 }
1019
1020 /// Creates a value from a one-shot iterator.
1021 ///
1022 /// This takes an iterator (yielding values that can be turned into a [`Value`])
1023 /// and wraps it in a way that it turns into an iterable value. From the view of
1024 /// the template this can be iterated over exactly once for the most part once
1025 /// exhausted.
1026 ///
1027 /// Such iterators are strongly recommended against in the general sense due to
1028 /// their surprising behavior, but they can be useful for more advanced use
1029 /// cases where data should be streamed into the template as it becomes available.
1030 ///
1031 /// Such iterators never have any size hints.
1032 ///
1033 /// ```
1034 /// # use minijinja::value::Value;
1035 /// let val = Value::make_one_shot_iterator(0..10);
1036 /// ```
1037 ///
1038 /// Attempting to iterate over it a second time will not yield any more items.
1039 pub fn make_one_shot_iterator<I, T>(iter: I) -> Value
1040 where
1041 I: Iterator<Item = T> + Send + Sync + 'static,
1042 T: Into<Value> + Send + Sync + 'static,
1043 {
1044 let iter = Arc::new(Mutex::new(iter.fuse()));
1045 Value::make_iterable(move || {
1046 let iter = iter.clone();
1047 std::iter::from_fn(move || iter.lock().unwrap().next())
1048 })
1049 }
1050
1051 /// Creates a callable value from a function.
1052 ///
1053 /// ```
1054 /// # use minijinja::value::Value;
1055 /// let pow = Value::from_function(|a: u32| a * a);
1056 /// ```
1057 pub fn from_function<F, Rv, Args>(f: F) -> Value
1058 where
1059 F: functions::Function<Rv, Args>,
1060 Rv: FunctionResult,
1061 Args: for<'a> FunctionArgs<'a>,
1062 {
1063 functions::BoxedFunction::new(f).to_value()
1064 }
1065
1066 /// Returns the kind of the value.
1067 ///
1068 /// This can be used to determine what's in the value before trying to
1069 /// perform operations on it.
1070 pub fn kind(&self) -> ValueKind {
1071 match self.0 {
1072 ValueRepr::Undefined(_) => ValueKind::Undefined,
1073 ValueRepr::Bool(_) => ValueKind::Bool,
1074 ValueRepr::U64(_) | ValueRepr::I64(_) | ValueRepr::F64(_) => ValueKind::Number,
1075 ValueRepr::None => ValueKind::None,
1076 ValueRepr::I128(_) => ValueKind::Number,
1077 ValueRepr::String(..) | ValueRepr::SmallStr(_) => ValueKind::String,
1078 ValueRepr::Bytes(_) => ValueKind::Bytes,
1079 ValueRepr::U128(_) => ValueKind::Number,
1080 ValueRepr::Invalid(_) => ValueKind::Invalid,
1081 ValueRepr::Object(ref obj) => match obj.repr() {
1082 ObjectRepr::Map => ValueKind::Map,
1083 ObjectRepr::Seq => ValueKind::Seq,
1084 ObjectRepr::Iterable => ValueKind::Iterable,
1085 ObjectRepr::Plain => ValueKind::Plain,
1086 },
1087 }
1088 }
1089
1090 /// Returns `true` if the value is a number.
1091 ///
1092 /// To convert a value into a primitive number, use [`TryFrom`] or [`TryInto`].
1093 pub fn is_number(&self) -> bool {
1094 matches!(
1095 self.0,
1096 ValueRepr::U64(_)
1097 | ValueRepr::I64(_)
1098 | ValueRepr::F64(_)
1099 | ValueRepr::I128(_)
1100 | ValueRepr::U128(_)
1101 )
1102 }
1103
1104 /// Returns true if the number is a real integer.
1105 ///
1106 /// This can be used to distinguish `42` from `42.0`. For the most part
1107 /// the engine keeps these the same.
1108 pub fn is_integer(&self) -> bool {
1109 matches!(
1110 self.0,
1111 ValueRepr::U64(_) | ValueRepr::I64(_) | ValueRepr::I128(_) | ValueRepr::U128(_)
1112 )
1113 }
1114
1115 /// Returns `true` if the map represents keyword arguments.
1116 pub fn is_kwargs(&self) -> bool {
1117 Kwargs::extract(self).is_some()
1118 }
1119
1120 /// Is this value considered true?
1121 ///
1122 /// The engine inherits the same behavior as Jinja2 when it comes to
1123 /// considering objects true. Empty objects are generally not considered
1124 /// true. For custom objects this is customized by [`Object::is_true`].
1125 pub fn is_true(&self) -> bool {
1126 match self.0 {
1127 ValueRepr::Bool(val) => val,
1128 ValueRepr::U64(x) => x != 0,
1129 ValueRepr::U128(x) => x.0 != 0,
1130 ValueRepr::I64(x) => x != 0,
1131 ValueRepr::I128(x) => x.0 != 0,
1132 ValueRepr::F64(x) => x != 0.0,
1133 ValueRepr::String(ref x, _) => !x.is_empty(),
1134 ValueRepr::SmallStr(ref x) => !x.is_empty(),
1135 ValueRepr::Bytes(ref x) => !x.is_empty(),
1136 ValueRepr::None | ValueRepr::Undefined(_) | ValueRepr::Invalid(_) => false,
1137 ValueRepr::Object(ref x) => x.is_true(),
1138 }
1139 }
1140
1141 /// Returns `true` if this value is safe.
1142 pub fn is_safe(&self) -> bool {
1143 matches!(&self.0, ValueRepr::String(_, StringType::Safe))
1144 }
1145
1146 /// Returns `true` if this value is undefined.
1147 pub fn is_undefined(&self) -> bool {
1148 matches!(&self.0, ValueRepr::Undefined(_))
1149 }
1150
1151 /// Returns `true` if this value is none.
1152 pub fn is_none(&self) -> bool {
1153 matches!(&self.0, ValueRepr::None)
1154 }
1155
1156 /// If the value is a string, return it.
1157 ///
1158 /// This will also perform a lossy string conversion of bytes from utf-8.
1159 pub fn to_str(&self) -> Option<Arc<str>> {
1160 match self.0 {
1161 ValueRepr::String(ref s, _) => Some(s.clone()),
1162 ValueRepr::SmallStr(ref s) => Some(Arc::from(s.as_str())),
1163 ValueRepr::Bytes(ref b) => Some(Arc::from(String::from_utf8_lossy(b))),
1164 _ => None,
1165 }
1166 }
1167
1168 /// If the value is a string, return it.
1169 ///
1170 /// This will also return well formed utf-8 bytes as string.
1171 pub fn as_str(&self) -> Option<&str> {
1172 match self.0 {
1173 ValueRepr::String(ref s, _) => Some(s as &str),
1174 ValueRepr::SmallStr(ref s) => Some(s.as_str()),
1175 ValueRepr::Bytes(ref b) => str::from_utf8(b).ok(),
1176 _ => None,
1177 }
1178 }
1179
1180 /// If this is an usize return it
1181 #[inline]
1182 pub fn as_usize(&self) -> Option<usize> {
1183 // This is manually implemented as the engine calls as_usize a few times
1184 // during execution on hotter paths. This way we can avoid an unnecessary clone.
1185 match self.0 {
1186 ValueRepr::I64(val) => TryFrom::try_from(val).ok(),
1187 ValueRepr::U64(val) => TryFrom::try_from(val).ok(),
1188 _ => self.clone().try_into().ok(),
1189 }
1190 }
1191
1192 /// If this is an i64 return it
1193 pub fn as_i64(&self) -> Option<i64> {
1194 i64::try_from(self.clone()).ok()
1195 }
1196
1197 /// Returns the bytes of this value if they exist.
1198 pub fn as_bytes(&self) -> Option<&[u8]> {
1199 match self.0 {
1200 ValueRepr::String(ref s, _) => Some(s.as_bytes()),
1201 ValueRepr::SmallStr(ref s) => Some(s.as_str().as_bytes()),
1202 ValueRepr::Bytes(ref b) => Some(&b[..]),
1203 _ => None,
1204 }
1205 }
1206
1207 /// If the value is an object a reference to it is returned.
1208 ///
1209 /// The returned value is a reference to a type erased [`DynObject`].
1210 /// For a specific type use [`downcast_object`](Self::downcast_object)
1211 /// instead.
1212 pub fn as_object(&self) -> Option<&DynObject> {
1213 match self.0 {
1214 ValueRepr::Object(ref dy) => Some(dy),
1215 _ => None,
1216 }
1217 }
1218
1219 /// Returns the length of the contained value.
1220 ///
1221 /// Values without a length will return `None`.
1222 ///
1223 /// ```
1224 /// # use minijinja::value::Value;
1225 /// let seq = Value::from(vec![1, 2, 3, 4]);
1226 /// assert_eq!(seq.len(), Some(4));
1227 /// ```
1228 pub fn len(&self) -> Option<usize> {
1229 match self.0 {
1230 ValueRepr::String(ref s, _) => Some(s.chars().count()),
1231 ValueRepr::SmallStr(ref s) => Some(s.as_str().chars().count()),
1232 ValueRepr::Bytes(ref b) => Some(b.len()),
1233 ValueRepr::Object(ref dy) => dy.enumerator_len(),
1234 _ => None,
1235 }
1236 }
1237
1238 /// Looks up an attribute by attribute name.
1239 ///
1240 /// This this returns [`UNDEFINED`](Self::UNDEFINED) when an invalid key is
1241 /// resolved. An error is returned if the value does not contain an object
1242 /// that has attributes.
1243 ///
1244 /// ```
1245 /// # use minijinja::value::Value;
1246 /// # fn test() -> Result<(), minijinja::Error> {
1247 /// let ctx = minijinja::context! {
1248 /// foo => "Foo"
1249 /// };
1250 /// let value = ctx.get_attr("foo")?;
1251 /// assert_eq!(value.to_string(), "Foo");
1252 /// # Ok(()) }
1253 /// ```
1254 pub fn get_attr(&self, key: &str) -> Result<Value, Error> {
1255 let value = match self.0 {
1256 ValueRepr::Undefined(_) => return Err(Error::from(ErrorKind::UndefinedError)),
1257 ValueRepr::Object(ref dy) => dy.get_value(&Value::from(key)),
1258 _ => None,
1259 };
1260
1261 Ok(value.unwrap_or(Value::UNDEFINED))
1262 }
1263
1264 /// Alternative lookup strategy without error handling exclusively for context
1265 /// resolution.
1266 ///
1267 /// The main difference is that the return value will be `None` if the value is
1268 /// unable to look up the key rather than returning `Undefined` and errors will
1269 /// also not be created.
1270 pub(crate) fn get_attr_fast(&self, key: &str) -> Option<Value> {
1271 match self.0 {
1272 ValueRepr::Object(ref dy) => dy.get_value(&Value::from(key)),
1273 _ => None,
1274 }
1275 }
1276
1277 /// Looks up an index of the value.
1278 ///
1279 /// This is a shortcut for [`get_item`](Self::get_item).
1280 ///
1281 /// ```
1282 /// # use minijinja::value::Value;
1283 /// let seq = Value::from(vec![0u32, 1, 2]);
1284 /// let value = seq.get_item_by_index(1).unwrap();
1285 /// assert_eq!(value.try_into().ok(), Some(1));
1286 /// ```
1287 pub fn get_item_by_index(&self, idx: usize) -> Result<Value, Error> {
1288 self.get_item(&Value(ValueRepr::U64(idx as _)))
1289 }
1290
1291 /// Looks up an item (or attribute) by key.
1292 ///
1293 /// This is similar to [`get_attr`](Self::get_attr) but instead of using
1294 /// a string key this can be any key. For instance this can be used to
1295 /// index into sequences. Like [`get_attr`](Self::get_attr) this returns
1296 /// [`UNDEFINED`](Self::UNDEFINED) when an invalid key is looked up.
1297 ///
1298 /// ```
1299 /// # use minijinja::value::Value;
1300 /// let ctx = minijinja::context! {
1301 /// foo => "Foo",
1302 /// };
1303 /// let value = ctx.get_item(&Value::from("foo")).unwrap();
1304 /// assert_eq!(value.to_string(), "Foo");
1305 /// ```
1306 pub fn get_item(&self, key: &Value) -> Result<Value, Error> {
1307 if let ValueRepr::Undefined(_) = self.0 {
1308 Err(Error::from(ErrorKind::UndefinedError))
1309 } else {
1310 Ok(self.get_item_opt(key).unwrap_or(Value::UNDEFINED))
1311 }
1312 }
1313
1314 /// Iterates over the value.
1315 ///
1316 /// Depending on the [`kind`](Self::kind) of the value the iterator
1317 /// has a different behavior.
1318 ///
1319 /// * [`ValueKind::Map`]: the iterator yields the keys of the map.
1320 /// * [`ValueKind::Seq`] / [`ValueKind::Iterable`]: the iterator yields the items in the sequence.
1321 /// * [`ValueKind::String`]: the iterator yields characters in a string.
1322 /// * [`ValueKind::None`] / [`ValueKind::Undefined`]: the iterator is empty.
1323 ///
1324 /// ```
1325 /// # use minijinja::value::Value;
1326 /// # fn test() -> Result<(), minijinja::Error> {
1327 /// let value = Value::from({
1328 /// let mut m = std::collections::BTreeMap::new();
1329 /// m.insert("foo", 42);
1330 /// m.insert("bar", 23);
1331 /// m
1332 /// });
1333 /// for key in value.try_iter()? {
1334 /// let value = value.get_item(&key)?;
1335 /// println!("{} = {}", key, value);
1336 /// }
1337 /// # Ok(()) }
1338 /// ```
1339 pub fn try_iter(&self) -> Result<ValueIter, Error> {
1340 match self.0 {
1341 ValueRepr::None | ValueRepr::Undefined(_) => Some(ValueIterImpl::Empty),
1342 ValueRepr::String(ref s, _) => {
1343 Some(ValueIterImpl::Chars(0, s.chars().count(), Arc::clone(s)))
1344 }
1345 ValueRepr::SmallStr(ref s) => Some(ValueIterImpl::Chars(
1346 0,
1347 s.as_str().chars().count(),
1348 Arc::from(s.as_str()),
1349 )),
1350 ValueRepr::Object(ref obj) => obj.try_iter().map(ValueIterImpl::Dyn),
1351 _ => None,
1352 }
1353 .map(|imp| ValueIter { imp })
1354 .ok_or_else(|| {
1355 Error::new(
1356 ErrorKind::InvalidOperation,
1357 format!("{} is not iterable", self.kind()),
1358 )
1359 })
1360 }
1361
1362 /// Returns a reversed view of this value.
1363 ///
1364 /// This is implemented for the following types with the following behaviors:
1365 ///
1366 /// * undefined or none: value returned unchanged.
1367 /// * string and bytes: returns a reversed version of that value
1368 /// * iterables: returns a reversed version of the iterable. If the iterable is not
1369 /// reversible itself, it consumes it and then reverses it.
1370 pub fn reverse(&self) -> Result<Value, Error> {
1371 match self.0 {
1372 ValueRepr::Undefined(_) | ValueRepr::None => Some(self.clone()),
1373 ValueRepr::String(ref s, _) => Some(Value::from(s.chars().rev().collect::<String>())),
1374 ValueRepr::SmallStr(ref s) => {
1375 // TODO: add small str optimization here
1376 Some(Value::from(s.as_str().chars().rev().collect::<String>()))
1377 }
1378 ValueRepr::Bytes(ref b) => Some(Value::from_bytes(
1379 b.iter().rev().copied().collect::<Vec<_>>(),
1380 )),
1381 ValueRepr::Object(ref o) => match o.enumerate() {
1382 Enumerator::NonEnumerable => None,
1383 Enumerator::Empty => Some(Value::make_iterable(|| None::<Value>.into_iter())),
1384 Enumerator::Seq(l) => {
1385 let self_clone = o.clone();
1386 Some(Value::make_iterable(move || {
1387 let self_clone = self_clone.clone();
1388 (0..l).rev().map(move |idx| {
1389 self_clone.get_value(&Value::from(idx)).unwrap_or_default()
1390 })
1391 }))
1392 }
1393 Enumerator::Iter(iter) => {
1394 let mut v = iter.collect::<Vec<_>>();
1395 v.reverse();
1396 Some(Value::make_object_iterable(v, move |v| {
1397 Box::new(v.iter().cloned())
1398 }))
1399 }
1400 Enumerator::RevIter(rev_iter) => {
1401 let for_restart = self.clone();
1402 let iter = Mutex::new(Some(rev_iter));
1403 Some(Value::make_iterable(move || {
1404 if let Some(iter) = iter.lock().unwrap().take() {
1405 Box::new(iter) as Box<dyn Iterator<Item = Value> + Send + Sync>
1406 } else {
1407 match for_restart.reverse().and_then(|x| x.try_iter()) {
1408 Ok(iterable) => Box::new(iterable)
1409 as Box<dyn Iterator<Item = Value> + Send + Sync>,
1410 Err(err) => Box::new(Some(Value::from(err)).into_iter())
1411 as Box<dyn Iterator<Item = Value> + Send + Sync>,
1412 }
1413 }
1414 }))
1415 }
1416 Enumerator::Str(s) => Some(Value::make_iterable(move || s.iter().rev().copied())),
1417 Enumerator::Values(mut v) => {
1418 v.reverse();
1419 Some(Value::make_object_iterable(v, move |v| {
1420 Box::new(v.iter().cloned())
1421 }))
1422 }
1423 },
1424 _ => None,
1425 }
1426 .ok_or_else(|| {
1427 Error::new(
1428 ErrorKind::InvalidOperation,
1429 format!("cannot reverse values of type {}", self.kind()),
1430 )
1431 })
1432 }
1433
1434 /// Returns some reference to the boxed object if it is of type `T`, or None if it isn’t.
1435 ///
1436 /// This is basically the "reverse" of [`from_object`](Self::from_object)
1437 /// and [`from_dyn_object`](Self::from_dyn_object). It's also a shortcut for
1438 /// [`downcast_ref`](DynObject::downcast_ref) on the return value of
1439 /// [`as_object`](Self::as_object).
1440 ///
1441 /// # Example
1442 ///
1443 /// ```rust
1444 /// # use minijinja::value::{Value, Object};
1445 /// use std::fmt;
1446 ///
1447 /// #[derive(Debug)]
1448 /// struct Thing {
1449 /// id: usize,
1450 /// }
1451 ///
1452 /// impl Object for Thing {}
1453 ///
1454 /// let x_value = Value::from_object(Thing { id: 42 });
1455 /// let thing = x_value.downcast_object_ref::<Thing>().unwrap();
1456 /// assert_eq!(thing.id, 42);
1457 /// ```
1458 pub fn downcast_object_ref<T: 'static>(&self) -> Option<&T> {
1459 match self.0 {
1460 ValueRepr::Object(ref o) => o.downcast_ref(),
1461 _ => None,
1462 }
1463 }
1464
1465 /// Like [`downcast_object_ref`](Self::downcast_object_ref) but returns
1466 /// the actual object.
1467 pub fn downcast_object<T: 'static>(&self) -> Option<Arc<T>> {
1468 match self.0 {
1469 ValueRepr::Object(ref o) => o.downcast(),
1470 _ => None,
1471 }
1472 }
1473
1474 pub(crate) fn get_item_opt(&self, key: &Value) -> Option<Value> {
1475 fn index(value: &Value, len: impl Fn() -> Option<usize>) -> Option<usize> {
1476 match value.as_i64().and_then(|v| isize::try_from(v).ok()) {
1477 Some(i) if i < 0 => some!(len()).checked_sub(i.unsigned_abs()),
1478 Some(i) => Some(i as usize),
1479 None => None,
1480 }
1481 }
1482
1483 match self.0 {
1484 ValueRepr::Object(ref dy) => match dy.repr() {
1485 ObjectRepr::Map | ObjectRepr::Plain => dy.get_value(key),
1486 ObjectRepr::Iterable => {
1487 if let Some(rv) = dy.get_value(key) {
1488 return Some(rv);
1489 }
1490 // The default behavior is to try to index into the iterable
1491 // as if nth() was called. This lets one slice an array and
1492 // then index into it.
1493 if let Some(idx) = index(key, || dy.enumerator_len()) {
1494 if let Some(mut iter) = dy.try_iter() {
1495 if let Some(rv) = iter.nth(idx) {
1496 return Some(rv);
1497 }
1498 }
1499 }
1500 None
1501 }
1502 ObjectRepr::Seq => {
1503 let idx = index(key, || dy.enumerator_len()).map(Value::from);
1504 dy.get_value(idx.as_ref().unwrap_or(key))
1505 }
1506 },
1507 ValueRepr::String(ref s, _) => {
1508 let idx = some!(index(key, || Some(s.chars().count())));
1509 s.chars().nth(idx).map(Value::from)
1510 }
1511 ValueRepr::SmallStr(ref s) => {
1512 let idx = some!(index(key, || Some(s.as_str().chars().count())));
1513 s.as_str().chars().nth(idx).map(Value::from)
1514 }
1515 ValueRepr::Bytes(ref b) => {
1516 let idx = some!(index(key, || Some(b.len())));
1517 b.get(idx).copied().map(Value::from)
1518 }
1519 _ => None,
1520 }
1521 }
1522
1523 /// Calls the value directly.
1524 ///
1525 /// If the value holds a function or macro, this invokes it. Note that in
1526 /// MiniJinja there is a separate namespace for methods on objects and callable
1527 /// items. To call methods (which should be a rather rare occurrence) you
1528 /// have to use [`call_method`](Self::call_method).
1529 ///
1530 /// The `args` slice is for the arguments of the function call. To pass
1531 /// keyword arguments use the [`Kwargs`] type.
1532 ///
1533 /// Usually the state is already available when it's useful to call this method,
1534 /// but when it's not available you can get a fresh template state straight
1535 /// from the [`Template`](crate::Template) via [`new_state`](crate::Template::new_state).
1536 ///
1537 /// ```
1538 /// # use minijinja::{Environment, value::{Value, Kwargs}};
1539 /// # let mut env = Environment::new();
1540 /// # env.add_template("foo", "").unwrap();
1541 /// # let tmpl = env.get_template("foo").unwrap();
1542 /// # let state = tmpl.new_state(); let state = &state;
1543 /// let func = Value::from_function(|v: i64, kwargs: Kwargs| {
1544 /// v * kwargs.get::<i64>("mult").unwrap_or(1)
1545 /// });
1546 /// let rv = func.call(
1547 /// state,
1548 /// &[
1549 /// Value::from(42),
1550 /// Value::from(Kwargs::from_iter([("mult", Value::from(2))])),
1551 /// ],
1552 /// ).unwrap();
1553 /// assert_eq!(rv, Value::from(84));
1554 /// ```
1555 ///
1556 /// With the [`args!`](crate::args) macro creating an argument slice is
1557 /// simplified:
1558 ///
1559 /// ```
1560 /// # use minijinja::{Environment, args, value::{Value, Kwargs}};
1561 /// # let mut env = Environment::new();
1562 /// # env.add_template("foo", "").unwrap();
1563 /// # let tmpl = env.get_template("foo").unwrap();
1564 /// # let state = tmpl.new_state(); let state = &state;
1565 /// let func = Value::from_function(|v: i64, kwargs: Kwargs| {
1566 /// v * kwargs.get::<i64>("mult").unwrap_or(1)
1567 /// });
1568 /// let rv = func.call(state, args!(42, mult => 2)).unwrap();
1569 /// assert_eq!(rv, Value::from(84));
1570 /// ```
1571 pub fn call(&self, state: &State, args: &[Value]) -> Result<Value, Error> {
1572 if let ValueRepr::Object(ref dy) = self.0 {
1573 dy.call(state, args)
1574 } else {
1575 Err(Error::new(
1576 ErrorKind::InvalidOperation,
1577 format!("value of type {} is not callable", self.kind()),
1578 ))
1579 }
1580 }
1581
1582 /// Calls a method on the value.
1583 ///
1584 /// The name of the method is `name`, the arguments passed are in the `args`
1585 /// slice.
1586 pub fn call_method(&self, state: &State, name: &str, args: &[Value]) -> Result<Value, Error> {
1587 match self._call_method(state, name, args) {
1588 Ok(rv) => Ok(rv),
1589 Err(mut err) => {
1590 if err.kind() == ErrorKind::UnknownMethod {
1591 if let Some(ref callback) = state.env().unknown_method_callback {
1592 match callback(state, self, name, args) {
1593 Ok(result) => return Ok(result),
1594 Err(callback_err) => {
1595 // if the callback fails with the same error, we
1596 // want to also attach the default detail if
1597 // it's missing
1598 if callback_err.kind() == ErrorKind::UnknownMethod {
1599 err = callback_err;
1600 } else {
1601 return Err(err);
1602 }
1603 }
1604 }
1605 }
1606 if err.detail().is_none() {
1607 err.set_detail(format!("{} has no method named {}", self.kind(), name));
1608 }
1609 }
1610 Err(err)
1611 }
1612 }
1613 }
1614
1615 fn _call_method(&self, state: &State, name: &str, args: &[Value]) -> Result<Value, Error> {
1616 if let Some(object) = self.as_object() {
1617 object.call_method(state, name, args)
1618 } else {
1619 Err(Error::from(ErrorKind::UnknownMethod))
1620 }
1621 }
1622
1623 #[cfg(feature = "builtins")]
1624 pub(crate) fn get_path(&self, path: &str) -> Result<Value, Error> {
1625 let mut rv = self.clone();
1626 for part in path.split('.') {
1627 if let Ok(num) = part.parse::<usize>() {
1628 rv = ok!(rv.get_item_by_index(num));
1629 } else {
1630 rv = ok!(rv.get_attr(part));
1631 }
1632 }
1633 Ok(rv)
1634 }
1635
1636 #[cfg(feature = "builtins")]
1637 pub(crate) fn get_path_or_default(&self, path: &str, default: &Value) -> Value {
1638 match self.get_path(path) {
1639 Err(_) => default.clone(),
1640 Ok(val) if val.is_undefined() => default.clone(),
1641 Ok(val) => val,
1642 }
1643 }
1644}
1645
1646impl Serialize for Value {
1647 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1648 where
1649 S: Serializer,
1650 {
1651 // enable round tripping of values
1652 if serializing_for_value() {
1653 let handle = LAST_VALUE_HANDLE.with(|x| {
1654 // we are okay with overflowing the handle here because these values only
1655 // live for a very short period of time and it's not likely that you run out
1656 // of an entire u32 worth of handles in a single serialization operation.
1657 let rv = x.get().wrapping_add(1);
1658 x.set(rv);
1659 rv
1660 });
1661 VALUE_HANDLES.with(|handles| handles.borrow_mut().insert(handle, self.clone()));
1662
1663 // we serialize this into a tuple struct as a form of in-band signalling
1664 // we can detect. This also will fail with a somewhat acceptable error
1665 // for flattening operations. See https://github.com/mitsuhiko/minijinja/issues/222
1666 let mut s = ok!(serializer.serialize_tuple_struct(VALUE_HANDLE_MARKER, 1));
1667 ok!(s.serialize_field(&handle));
1668 return s.end();
1669 }
1670
1671 match self.0 {
1672 ValueRepr::Bool(b) => serializer.serialize_bool(b),
1673 ValueRepr::U64(u) => serializer.serialize_u64(u),
1674 ValueRepr::I64(i) => serializer.serialize_i64(i),
1675 ValueRepr::F64(f) => serializer.serialize_f64(f),
1676 ValueRepr::None | ValueRepr::Undefined(_) | ValueRepr::Invalid(_) => {
1677 serializer.serialize_unit()
1678 }
1679 ValueRepr::U128(u) => serializer.serialize_u128(u.0),
1680 ValueRepr::I128(i) => serializer.serialize_i128(i.0),
1681 ValueRepr::String(ref s, _) => serializer.serialize_str(s),
1682 ValueRepr::SmallStr(ref s) => serializer.serialize_str(s.as_str()),
1683 ValueRepr::Bytes(ref b) => serializer.serialize_bytes(b),
1684 ValueRepr::Object(ref o) => match o.repr() {
1685 ObjectRepr::Plain => serializer.serialize_str(&o.to_string()),
1686 ObjectRepr::Seq | ObjectRepr::Iterable => {
1687 use serde::ser::SerializeSeq;
1688 let mut seq = ok!(serializer.serialize_seq(o.enumerator_len()));
1689 if let Some(iter) = o.try_iter() {
1690 for item in iter {
1691 ok!(seq.serialize_element(&item));
1692 }
1693 }
1694
1695 seq.end()
1696 }
1697 ObjectRepr::Map => {
1698 use serde::ser::SerializeMap;
1699 let mut map = ok!(serializer.serialize_map(None));
1700 if let Some(iter) = o.try_iter_pairs() {
1701 for (key, value) in iter {
1702 ok!(map.serialize_entry(&key, &value));
1703 }
1704 }
1705
1706 map.end()
1707 }
1708 },
1709 }
1710 }
1711}
1712
1713/// Helper to create an iterator proxy that borrows from an object.
1714pub(crate) fn mapped_enumerator<F, T>(obj: &Arc<T>, maker: F) -> Enumerator
1715where
1716 T: Object + 'static,
1717 F: for<'a> FnOnce(&'a T) -> Box<dyn Iterator<Item = Value> + Send + Sync + 'a>,
1718{
1719 struct Iter {
1720 iter: Box<dyn Iterator<Item = Value> + Send + Sync + 'static>,
1721 _object: DynObject,
1722 }
1723
1724 impl Iterator for Iter {
1725 type Item = Value;
1726
1727 fn next(&mut self) -> Option<Self::Item> {
1728 self.iter.next()
1729 }
1730
1731 fn size_hint(&self) -> (usize, Option<usize>) {
1732 self.iter.size_hint()
1733 }
1734 }
1735
1736 // SAFETY: this is safe because the object is kept alive by the iter
1737 let iter = unsafe {
1738 std::mem::transmute::<Box<dyn Iterator<Item = _>>, Box<dyn Iterator<Item = _> + Send + Sync>>(
1739 maker(obj),
1740 )
1741 };
1742 let _object = DynObject::new(obj.clone());
1743 Enumerator::Iter(Box::new(Iter { iter, _object }))
1744}
1745
1746/// Utility to iterate over values.
1747pub struct ValueIter {
1748 imp: ValueIterImpl,
1749}
1750
1751impl Iterator for ValueIter {
1752 type Item = Value;
1753
1754 fn next(&mut self) -> Option<Self::Item> {
1755 match self.imp {
1756 ValueIterImpl::Empty => None,
1757 ValueIterImpl::Chars(ref mut offset, ref mut len, ref s) => {
1758 (s as &str)[*offset..].chars().next().map(|c| {
1759 *offset += c.len_utf8();
1760 *len -= 1;
1761 Value::from(c)
1762 })
1763 }
1764 ValueIterImpl::Dyn(ref mut iter) => iter.next(),
1765 }
1766 }
1767
1768 fn size_hint(&self) -> (usize, Option<usize>) {
1769 match self.imp {
1770 ValueIterImpl::Empty => (0, Some(0)),
1771 ValueIterImpl::Chars(_, len, _) => (0, Some(len)),
1772 ValueIterImpl::Dyn(ref iter) => iter.size_hint(),
1773 }
1774 }
1775}
1776
1777impl fmt::Debug for ValueIter {
1778 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1779 f.debug_struct("ValueIterator").finish()
1780 }
1781}
1782
1783enum ValueIterImpl {
1784 Empty,
1785 Chars(usize, usize, Arc<str>),
1786 Dyn(Box<dyn Iterator<Item = Value> + Send + Sync>),
1787}
1788
1789impl From<Error> for Value {
1790 fn from(value: Error) -> Self {
1791 Value(ValueRepr::Invalid(Arc::new(value)))
1792 }
1793}
1794
1795#[cfg(test)]
1796mod tests {
1797 use super::*;
1798
1799 use similar_asserts::assert_eq;
1800
1801 #[test]
1802 fn test_dynamic_object_roundtrip() {
1803 use std::sync::atomic::{self, AtomicUsize};
1804
1805 #[derive(Debug, Clone)]
1806 struct X(Arc<AtomicUsize>);
1807
1808 impl Object for X {
1809 fn get_value(self: &Arc<Self>, key: &Value) -> Option<Value> {
1810 match key.as_str()? {
1811 "value" => Some(Value::from(self.0.load(atomic::Ordering::Relaxed))),
1812 _ => None,
1813 }
1814 }
1815
1816 fn enumerate(self: &Arc<Self>) -> Enumerator {
1817 Enumerator::Str(&["value"])
1818 }
1819
1820 fn render(self: &Arc<Self>, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1821 write!(f, "{}", self.0.load(atomic::Ordering::Relaxed))
1822 }
1823 }
1824
1825 let x = Arc::new(X(Default::default()));
1826 let x_value = Value::from_dyn_object(x.clone());
1827 x.0.fetch_add(42, atomic::Ordering::Relaxed);
1828 let x_clone = Value::from_serialize(&x_value);
1829 x.0.fetch_add(23, atomic::Ordering::Relaxed);
1830
1831 assert_eq!(x_value.to_string(), "65");
1832 assert_eq!(x_clone.to_string(), "65");
1833 }
1834
1835 #[test]
1836 fn test_string_char() {
1837 let val = Value::from('a');
1838 assert_eq!(char::try_from(val).unwrap(), 'a');
1839 let val = Value::from("a");
1840 assert_eq!(char::try_from(val).unwrap(), 'a');
1841 let val = Value::from("wat");
1842 assert!(char::try_from(val).is_err());
1843 }
1844
1845 #[test]
1846 #[cfg(target_pointer_width = "64")]
1847 fn test_sizes() {
1848 assert_eq!(std::mem::size_of::<Value>(), 24);
1849 }
1850}