minijinja/value/
argtypes.rs

1use std::borrow::Cow;
2use std::cell::RefCell;
3use std::collections::HashSet;
4use std::ops::{Deref, DerefMut};
5use std::sync::Arc;
6
7use crate::error::{Error, ErrorKind};
8use crate::value::{
9    DynObject, ObjectExt, ObjectRepr, Packed, SmallStr, StringType, Value, ValueKind, ValueMap,
10    ValueRepr,
11};
12use crate::vm::State;
13
14use super::{Enumerator, Object};
15
16/// A utility trait that represents the return value of functions, filters and tests.
17///
18/// It's implemented for the following types:
19///
20/// * `Rv` where `Rv` implements `Into<AnyMapObject>`
21/// * `Result<Rv, Error>` where `Rv` implements `Into<Value>`
22pub trait FunctionResult {
23    #[doc(hidden)]
24    fn into_result(self) -> Result<Value, Error>;
25}
26
27impl<I: Into<Value>> FunctionResult for Result<I, Error> {
28    fn into_result(self) -> Result<Value, Error> {
29        self.map(Into::into)
30    }
31}
32
33impl<I: Into<Value>> FunctionResult for I {
34    fn into_result(self) -> Result<Value, Error> {
35        Ok(self.into())
36    }
37}
38
39/// Helper trait representing valid filter, test and function arguments.
40///
41/// Since it's more convenient to write filters and tests with concrete
42/// types instead of values, this helper trait exists to automatically
43/// perform this conversion.  It is implemented for functions up to an
44/// arity of 5 parameters.
45///
46/// For each argument the conversion is performed via the [`ArgType`]
47/// trait which is implemented for many common types.  For manual
48/// conversions the [`from_args`] utility should be used.
49pub trait FunctionArgs<'a> {
50    /// The output type of the function arguments.
51    type Output;
52
53    /// Converts to function arguments from a slice of values.
54    #[doc(hidden)]
55    fn from_values(state: Option<&'a State>, values: &'a [Value]) -> Result<Self::Output, Error>;
56}
57
58/// Utility function to convert a slice of values into arguments.
59///
60/// This performs the same conversion that [`Function`](crate::functions::Function)
61/// performs.  It exists so that you one can leverage the same functionality when
62/// implementing [`Object::call_method`](crate::value::Object::call_method).
63///
64/// ```
65/// # use minijinja::value::from_args;
66/// # use minijinja::value::Value;
67/// # fn foo() -> Result<(), minijinja::Error> {
68/// # let args = vec![Value::from("foo"), Value::from(42i64)]; let args = &args[..];
69/// // args is &[Value]
70/// let (string, num): (&str, i64) = from_args(args)?;
71/// # Ok(()) } fn main() { foo().unwrap(); }
72/// ```
73///
74/// Note that only value conversions are supported which means that `&State` is not
75/// a valid conversion type.
76///
77/// You can also use this function to split positional and keyword arguments ([`Kwargs`]):
78///
79/// ```
80/// # use minijinja::value::{Value, Rest, Kwargs, from_args};
81/// # use minijinja::Error;
82/// # fn foo() -> Result<(), minijinja::Error> {
83/// # let args = vec![Value::from("foo"), Value::from(42i64)]; let args = &args[..];
84/// // args is &[Value], kwargs is Kwargs
85/// let (args, kwargs): (&[Value], Kwargs) = from_args(args)?;
86/// # Ok(())
87/// # } fn main() { foo().unwrap(); }
88/// ```
89#[inline(always)]
90pub fn from_args<'a, Args>(values: &'a [Value]) -> Result<Args, Error>
91where
92    Args: FunctionArgs<'a, Output = Args>,
93{
94    Args::from_values(None, values)
95}
96
97/// A trait implemented by all filter/test argument types.
98///
99/// This trait is used by [`FunctionArgs`].  It's implemented for many common
100/// types that are typically passed to filters, tests or functions.  It's
101/// implemented for the following types:
102///
103/// * eval state: [`&State`](crate::State) (see below for notes)
104/// * unsigned integers: [`u8`], [`u16`], [`u32`], [`u64`], [`u128`], [`usize`]
105/// * signed integers: [`i8`], [`i16`], [`i32`], [`i64`], [`i128`]
106/// * floats: [`f32`], [`f64`]
107/// * bool: [`bool`]
108/// * string: [`String`], [`&str`], `Cow<'_, str>`, [`char`]
109/// * bytes: [`&[u8]`][`slice`]
110/// * values: [`Value`], `&Value`
111/// * vectors: [`Vec<T>`]
112/// * objects: [`DynObject`], [`Arc<T>`], `&T` (where `T` is an [`Object`])
113/// * serde deserializable: [`ViaDeserialize<T>`](crate::value::deserialize::ViaDeserialize)
114/// * keyword arguments: [`Kwargs`]
115/// * leftover arguments: [`Rest<T>`]
116///
117/// The type is also implemented for optional values (`Option<T>`) which is used
118/// to encode optional parameters to filters, functions or tests.  Additionally
119/// it's implemented for [`Rest<T>`] which is used to encode the remaining arguments
120/// of a function call.
121///
122/// ## Notes on Borrowing
123///
124/// Note on that there is an important difference between `String` and `&str`:
125/// the former will be valid for all values and an implicit conversion to string
126/// via [`ToString`] will take place, for the latter only values which are already
127/// strings will be passed.  A compromise between the two is `Cow<'_, str>` which
128/// will behave like `String` but borrows when possible.
129///
130/// Byte slices will borrow out of values carrying bytes or strings.  In the latter
131/// case the utf-8 bytes are returned.
132///
133/// There are also further restrictions imposed on borrowing in some situations.
134/// For instance you cannot implicitly borrow out of sequences which means that
135/// for instance `Vec<&str>` is not a legal argument.
136///
137/// ## Notes on State
138///
139/// When `&State` is used, it does not consume a passed parameter.  This means that
140/// a filter that takes `(&State, String)` actually only has one argument.  The
141/// state is passed implicitly.
142pub trait ArgType<'a> {
143    /// The output type of this argument.
144    type Output;
145
146    #[doc(hidden)]
147    fn from_value(value: Option<&'a Value>) -> Result<Self::Output, Error>;
148
149    #[doc(hidden)]
150    fn from_value_owned(_value: Value) -> Result<Self::Output, Error> {
151        Err(Error::new(
152            ErrorKind::InvalidOperation,
153            "type conversion is not legal in this situation (implicit borrow)",
154        ))
155    }
156
157    #[doc(hidden)]
158    fn from_state_and_value(
159        _state: Option<&'a State>,
160        value: Option<&'a Value>,
161    ) -> Result<(Self::Output, usize), Error> {
162        Ok((ok!(Self::from_value(value)), 1))
163    }
164
165    #[doc(hidden)]
166    #[inline(always)]
167    fn from_state_and_values(
168        state: Option<&'a State>,
169        values: &'a [Value],
170        offset: usize,
171    ) -> Result<(Self::Output, usize), Error> {
172        Self::from_state_and_value(state, values.get(offset))
173    }
174
175    #[doc(hidden)]
176    #[inline(always)]
177    fn is_trailing() -> bool {
178        false
179    }
180}
181
182macro_rules! tuple_impls {
183    ( $( $name:ident )* * $rest_name:ident ) => {
184        impl<'a, $($name,)* $rest_name> FunctionArgs<'a> for ($($name,)* $rest_name,)
185            where $($name: ArgType<'a>,)* $rest_name: ArgType<'a>
186        {
187            type Output = ($($name::Output,)* $rest_name::Output ,);
188
189            fn from_values(state: Option<&'a State>, mut values: &'a [Value]) -> Result<Self::Output, Error> {
190                #![allow(non_snake_case, unused)]
191                $( let $name; )*
192                let mut $rest_name = None;
193                let mut idx = 0;
194
195                // special case: the last type is marked trailing (eg: for Kwargs) and we have at
196                // least one value.  In that case we need to read it first before going to the rest
197                // of the arguments.  This is needed to support from_args::<(&[Value], Kwargs)>
198                // or similar.
199                let rest_first = $rest_name::is_trailing() && !values.is_empty();
200                if rest_first {
201                    let (val, offset) = ok!($rest_name::from_state_and_values(state, values, values.len() - 1));
202                    $rest_name = Some(val);
203                    values = &values[..values.len() - offset];
204                }
205                $(
206                    let (val, offset) = ok!($name::from_state_and_values(state, values, idx));
207                    $name = val;
208                    idx += offset;
209                )*
210
211                if !rest_first {
212                    let (val, offset) = ok!($rest_name::from_state_and_values(state, values, idx));
213                    $rest_name = Some(val);
214                    idx += offset;
215                }
216
217                if values.get(idx).is_some() {
218                    Err(Error::from(ErrorKind::TooManyArguments))
219                } else {
220                    // SAFETY: this is safe because both no matter what `rest_first` is set to
221                    // the rest_name variable is set at this point.
222                    Ok(($($name,)* unsafe { $rest_name.unwrap_unchecked() },))
223                }
224            }
225        }
226    };
227}
228
229impl<'a> FunctionArgs<'a> for () {
230    type Output = ();
231
232    fn from_values(_state: Option<&'a State>, values: &'a [Value]) -> Result<Self::Output, Error> {
233        if values.is_empty() {
234            Ok(())
235        } else {
236            Err(Error::from(ErrorKind::TooManyArguments))
237        }
238    }
239}
240
241tuple_impls! { *A }
242tuple_impls! { A *B }
243tuple_impls! { A B *C }
244tuple_impls! { A B C *D }
245tuple_impls! { A B C D *E }
246
247impl From<ValueRepr> for Value {
248    #[inline(always)]
249    fn from(val: ValueRepr) -> Value {
250        Value(val)
251    }
252}
253
254impl<'a> From<&'a [u8]> for Value {
255    #[inline(always)]
256    fn from(val: &'a [u8]) -> Self {
257        ValueRepr::Bytes(Arc::new(val.into())).into()
258    }
259}
260
261impl<'a> From<&'a str> for Value {
262    #[inline(always)]
263    fn from(val: &'a str) -> Self {
264        SmallStr::try_new(val)
265            .map(|small_str| Value(ValueRepr::SmallStr(small_str)))
266            .unwrap_or_else(|| Value(ValueRepr::String(val.into(), StringType::Normal)))
267    }
268}
269
270impl<'a> From<&'a String> for Value {
271    #[inline(always)]
272    fn from(val: &'a String) -> Self {
273        Value::from(val.as_str())
274    }
275}
276
277impl From<String> for Value {
278    #[inline(always)]
279    fn from(val: String) -> Self {
280        // There is no benefit here of "reusing" the string allocation.  The reason
281        // is that From<String> for Arc<str> copies the bytes over anyways.
282        Value::from(val.as_str())
283    }
284}
285
286impl<'a> From<Cow<'a, str>> for Value {
287    #[inline(always)]
288    fn from(val: Cow<'a, str>) -> Self {
289        match val {
290            Cow::Borrowed(x) => x.into(),
291            Cow::Owned(x) => x.into(),
292        }
293    }
294}
295
296impl From<Arc<str>> for Value {
297    fn from(value: Arc<str>) -> Self {
298        Value(ValueRepr::String(value, StringType::Normal))
299    }
300}
301
302impl From<()> for Value {
303    #[inline(always)]
304    fn from(_: ()) -> Self {
305        ValueRepr::None.into()
306    }
307}
308
309impl<V: Into<Value>> FromIterator<V> for Value {
310    fn from_iter<T: IntoIterator<Item = V>>(iter: T) -> Self {
311        Value::from_object(iter.into_iter().map(Into::into).collect::<Vec<Value>>())
312    }
313}
314
315impl<K: Into<Value>, V: Into<Value>> FromIterator<(K, V)> for Value {
316    fn from_iter<T: IntoIterator<Item = (K, V)>>(iter: T) -> Self {
317        Value::from_object(
318            iter.into_iter()
319                .map(|(k, v)| (k.into(), v.into()))
320                .collect::<ValueMap>(),
321        )
322    }
323}
324
325macro_rules! value_from {
326    ($src:ty, $dst:ident) => {
327        impl From<$src> for Value {
328            #[inline(always)]
329            fn from(val: $src) -> Self {
330                ValueRepr::$dst(val as _).into()
331            }
332        }
333    };
334}
335
336impl From<i128> for Value {
337    #[inline(always)]
338    fn from(val: i128) -> Self {
339        ValueRepr::I128(Packed(val)).into()
340    }
341}
342
343impl From<u128> for Value {
344    #[inline(always)]
345    fn from(val: u128) -> Self {
346        ValueRepr::U128(Packed(val)).into()
347    }
348}
349
350impl From<char> for Value {
351    #[inline(always)]
352    fn from(val: char) -> Self {
353        let mut buf = [0u8; 4];
354        ValueRepr::SmallStr(SmallStr::try_new(val.encode_utf8(&mut buf)).unwrap()).into()
355    }
356}
357
358value_from!(bool, Bool);
359value_from!(u8, U64);
360value_from!(u16, U64);
361value_from!(u32, U64);
362value_from!(u64, U64);
363value_from!(i8, I64);
364value_from!(i16, I64);
365value_from!(i32, I64);
366value_from!(i64, I64);
367value_from!(f32, F64);
368value_from!(f64, F64);
369value_from!(Arc<Vec<u8>>, Bytes);
370value_from!(DynObject, Object);
371
372fn unsupported_conversion(kind: ValueKind, target: &str) -> Error {
373    Error::new(
374        ErrorKind::InvalidOperation,
375        format!("cannot convert {kind} to {target}"),
376    )
377}
378
379macro_rules! primitive_try_from {
380    ($ty:ident, {
381        $($pat:pat $(if $if_expr:expr)? => $expr:expr,)*
382    }) => {
383        impl TryFrom<Value> for $ty {
384            type Error = Error;
385
386            fn try_from(value: Value) -> Result<Self, Self::Error> {
387                match value.0 {
388                    $($pat $(if $if_expr)? => TryFrom::try_from($expr).ok(),)*
389                    _ => None
390                }.ok_or_else(|| unsupported_conversion(value.kind(), stringify!($ty)))
391            }
392        }
393
394        impl<'a> ArgType<'a> for $ty {
395            type Output = Self;
396            fn from_value(value: Option<&Value>) -> Result<Self, Error> {
397                match value {
398                    Some(value) => TryFrom::try_from(value.clone()),
399                    None => Err(Error::from(ErrorKind::MissingArgument))
400                }
401            }
402
403            fn from_value_owned(value: Value) -> Result<Self, Error> {
404                TryFrom::try_from(value)
405            }
406        }
407    }
408}
409
410macro_rules! primitive_int_try_from {
411    ($ty:ident) => {
412        primitive_try_from!($ty, {
413            ValueRepr::Bool(val) => val as usize,
414            ValueRepr::I64(val) => val,
415            ValueRepr::U64(val) => val,
416            // for the intention here see Key::from_borrowed_value
417            ValueRepr::F64(val) if (val as i64 as f64 == val) => val as i64,
418            ValueRepr::I128(val) => val.0,
419            ValueRepr::U128(val) => val.0,
420        });
421    }
422}
423
424primitive_int_try_from!(u8);
425primitive_int_try_from!(u16);
426primitive_int_try_from!(u32);
427primitive_int_try_from!(u64);
428primitive_int_try_from!(u128);
429primitive_int_try_from!(i8);
430primitive_int_try_from!(i16);
431primitive_int_try_from!(i32);
432primitive_int_try_from!(i64);
433primitive_int_try_from!(i128);
434primitive_int_try_from!(usize);
435
436primitive_try_from!(bool, {
437    ValueRepr::Bool(val) => val,
438});
439primitive_try_from!(char, {
440    ValueRepr::String(ref val, _) => {
441        let mut char_iter = val.chars();
442        ok!(char_iter.next().filter(|_| char_iter.next().is_none()).ok_or_else(|| {
443            unsupported_conversion(ValueKind::String, "non single character string")
444        }))
445    },
446    ValueRepr::SmallStr(ref val) => {
447        let mut char_iter = val.as_str().chars();
448        ok!(char_iter.next().filter(|_| char_iter.next().is_none()).ok_or_else(|| {
449            unsupported_conversion(ValueKind::String, "non single character string")
450        }))
451    },
452});
453primitive_try_from!(f32, {
454    ValueRepr::U64(val) => val as f32,
455    ValueRepr::I64(val) => val as f32,
456    ValueRepr::U128(val) => val.0 as f32,
457    ValueRepr::I128(val) => val.0 as f32,
458    ValueRepr::F64(val) => val as f32,
459});
460primitive_try_from!(f64, {
461    ValueRepr::U64(val) => val as f64,
462    ValueRepr::I64(val) => val as f64,
463    ValueRepr::U128(val) => val.0 as f64,
464    ValueRepr::I128(val) => val.0 as f64,
465    ValueRepr::F64(val) => val,
466});
467
468impl<'a> ArgType<'a> for &str {
469    type Output = &'a str;
470
471    fn from_value(value: Option<&'a Value>) -> Result<Self::Output, Error> {
472        match value {
473            Some(value) => value
474                .as_str()
475                .ok_or_else(|| Error::new(ErrorKind::InvalidOperation, "value is not a string")),
476            None => Err(Error::from(ErrorKind::MissingArgument)),
477        }
478    }
479}
480
481impl TryFrom<Value> for Arc<str> {
482    type Error = Error;
483
484    fn try_from(value: Value) -> Result<Self, Self::Error> {
485        match value.0 {
486            ValueRepr::String(x, _) => Ok(x),
487            ValueRepr::SmallStr(x) => Ok(Arc::from(x.as_str())),
488            ValueRepr::Bytes(ref x) => Ok(Arc::from(String::from_utf8_lossy(x))),
489            _ => Err(Error::new(
490                ErrorKind::InvalidOperation,
491                "value is not a string",
492            )),
493        }
494    }
495}
496
497impl<'a> ArgType<'a> for Arc<str> {
498    type Output = Arc<str>;
499
500    fn from_value(value: Option<&'a Value>) -> Result<Self::Output, Error> {
501        match value {
502            Some(value) => TryFrom::try_from(value.clone()),
503            None => Err(Error::from(ErrorKind::MissingArgument)),
504        }
505    }
506}
507
508impl<'a> ArgType<'a> for &[u8] {
509    type Output = &'a [u8];
510
511    fn from_value(value: Option<&'a Value>) -> Result<Self::Output, Error> {
512        match value {
513            Some(value) => value
514                .as_bytes()
515                .ok_or_else(|| Error::new(ErrorKind::InvalidOperation, "value is not in bytes")),
516            None => Err(Error::from(ErrorKind::MissingArgument)),
517        }
518    }
519}
520
521impl<'a, T: ArgType<'a>> ArgType<'a> for Option<T> {
522    type Output = Option<T::Output>;
523
524    fn from_value(value: Option<&'a Value>) -> Result<Self::Output, Error> {
525        match value {
526            Some(value) => {
527                if value.is_undefined() || value.is_none() {
528                    Ok(None)
529                } else {
530                    T::from_value(Some(value)).map(Some)
531                }
532            }
533            None => Ok(None),
534        }
535    }
536
537    fn from_value_owned(value: Value) -> Result<Self::Output, Error> {
538        if value.is_undefined() || value.is_none() {
539            Ok(None)
540        } else {
541            T::from_value_owned(value).map(Some)
542        }
543    }
544}
545
546impl<'a> ArgType<'a> for Cow<'_, str> {
547    type Output = Cow<'a, str>;
548
549    #[inline(always)]
550    fn from_value(value: Option<&'a Value>) -> Result<Cow<'a, str>, Error> {
551        match value {
552            Some(value) => Ok(match value.0 {
553                ValueRepr::String(ref s, _) => Cow::Borrowed(s as &str),
554                ValueRepr::SmallStr(ref s) => Cow::Borrowed(s.as_str()),
555                _ => {
556                    if value.is_kwargs() {
557                        return Err(Error::new(
558                            ErrorKind::InvalidOperation,
559                            "cannot convert kwargs to string",
560                        ));
561                    }
562                    Cow::Owned(value.to_string())
563                }
564            }),
565            None => Err(Error::from(ErrorKind::MissingArgument)),
566        }
567    }
568}
569
570impl<'a> ArgType<'a> for &Value {
571    type Output = &'a Value;
572
573    #[inline(always)]
574    fn from_value(value: Option<&'a Value>) -> Result<&'a Value, Error> {
575        match value {
576            Some(value) => Ok(value),
577            None => Err(Error::from(ErrorKind::MissingArgument)),
578        }
579    }
580}
581
582impl<'a> ArgType<'a> for &[Value] {
583    type Output = &'a [Value];
584
585    #[inline(always)]
586    fn from_value(value: Option<&'a Value>) -> Result<&'a [Value], Error> {
587        match value {
588            Some(value) => Ok(std::slice::from_ref(value)),
589            None => Err(Error::from(ErrorKind::MissingArgument)),
590        }
591    }
592
593    fn from_state_and_values(
594        _state: Option<&'a State>,
595        values: &'a [Value],
596        offset: usize,
597    ) -> Result<(&'a [Value], usize), Error> {
598        let args = values.get(offset..).unwrap_or_default();
599        Ok((args, args.len()))
600    }
601}
602
603impl<'a, T: Object + 'static> ArgType<'a> for &T {
604    type Output = &'a T;
605
606    #[inline(always)]
607    fn from_value(value: Option<&'a Value>) -> Result<Self::Output, Error> {
608        match value {
609            Some(value) => value
610                .downcast_object_ref()
611                .ok_or_else(|| Error::new(ErrorKind::InvalidOperation, "expected object")),
612            None => Err(Error::from(ErrorKind::MissingArgument)),
613        }
614    }
615}
616
617impl<'a, T: Object + 'static> ArgType<'a> for Arc<T> {
618    type Output = Arc<T>;
619
620    #[inline(always)]
621    fn from_value(value: Option<&'a Value>) -> Result<Self::Output, Error> {
622        match value {
623            Some(value) => value
624                .downcast_object()
625                .ok_or_else(|| Error::new(ErrorKind::InvalidOperation, "expected object")),
626            None => Err(Error::from(ErrorKind::MissingArgument)),
627        }
628    }
629}
630
631/// Utility type to capture remaining arguments.
632///
633/// In some cases you might want to have a variadic function.  In that case
634/// you can define the last argument to a [`Function`](crate::functions::Function)
635/// this way.  The `Rest<T>` type will collect all the remaining arguments
636/// here.  It's implemented for all [`ArgType`]s.  The type itself deref's
637/// into the inner vector.
638///
639/// ```
640/// # use minijinja::Environment;
641/// # let mut env = Environment::new();
642/// use minijinja::State;
643/// use minijinja::value::Rest;
644///
645/// fn sum(_state: &State, values: Rest<i64>) -> i64 {
646///     values.iter().sum()
647/// }
648/// ```
649#[derive(Debug)]
650pub struct Rest<T>(pub Vec<T>);
651
652impl<T> Deref for Rest<T> {
653    type Target = Vec<T>;
654
655    fn deref(&self) -> &Self::Target {
656        &self.0
657    }
658}
659
660impl<T> DerefMut for Rest<T> {
661    fn deref_mut(&mut self) -> &mut Self::Target {
662        &mut self.0
663    }
664}
665
666impl<'a, T: ArgType<'a, Output = T>> ArgType<'a> for Rest<T> {
667    type Output = Self;
668
669    fn from_value(value: Option<&'a Value>) -> Result<Self, Error> {
670        Ok(Rest(ok!(value
671            .iter()
672            .map(|v| T::from_value(Some(v)))
673            .collect::<Result<_, _>>())))
674    }
675
676    fn from_state_and_values(
677        _state: Option<&'a State>,
678        values: &'a [Value],
679        offset: usize,
680    ) -> Result<(Self, usize), Error> {
681        let args = values.get(offset..).unwrap_or_default();
682        Ok((
683            Rest(ok!(args
684                .iter()
685                .map(|v| T::from_value(Some(v)))
686                .collect::<Result<_, _>>())),
687            args.len(),
688        ))
689    }
690}
691
692/// Utility to accept keyword arguments.
693///
694/// Keyword arguments are represented as regular values as the last argument
695/// in an argument list.  This can be quite complex to use manually so this
696/// type is added as a utility.  You can use [`get`](Self::get) to fetch a
697/// single keyword argument and then use [`assert_all_used`](Self::assert_all_used)
698/// to make sure extra arguments create an error.
699///
700/// Here an example of a function modifying values in different ways.
701///
702/// ```
703/// use minijinja::value::{Value, Kwargs};
704/// use minijinja::Error;
705///
706/// fn modify(mut values: Vec<Value>, options: Kwargs) -> Result<Vec<Value>, Error> {
707///     // get pulls a parameter of any type.  Same as from_args.  For optional
708///     // boolean values the type inference is particularly convenient.
709///     if let Some(true) = options.get("reverse")? {
710///         values.reverse();
711///     }
712///     if let Some(limit) = options.get("limit")? {
713///         values.truncate(limit);
714///     }
715///     options.assert_all_used()?;
716///     Ok(values)
717/// }
718/// ```
719///
720/// If for whatever reason you need a value again you can use [`Into`] to
721/// convert it back into a [`Value`].  This is particularly useful when performing
722/// calls into values.  To create a [`Kwargs`] object from scratch you can use
723/// [`FromIterator`]:
724///
725/// ```
726/// use minijinja::value::{Value, Kwargs};
727/// let kwargs = Kwargs::from_iter([
728///     ("foo", Value::from(true)),
729///     ("bar", Value::from(42)),
730/// ]);
731/// let value = Value::from(kwargs);
732/// assert!(value.is_kwargs());
733/// ```
734///
735/// When working with [`Rest`] you can use [`from_args`] to split all arguments into
736/// positional arguments and keyword arguments:
737///
738/// ```
739/// # use minijinja::value::{Value, Rest, Kwargs, from_args};
740/// # use minijinja::Error;
741/// fn my_func(args: Rest<Value>) -> Result<Value, Error> {
742///     let (args, kwargs) = from_args::<(&[Value], Kwargs)>(&args)?;
743///     // do something with args and kwargs
744/// # todo!()
745/// }
746/// ```
747#[derive(Debug, Clone)]
748pub struct Kwargs {
749    pub(crate) values: Arc<KwargsValues>,
750    used: RefCell<HashSet<String>>,
751}
752
753#[repr(transparent)]
754#[derive(Default, Debug)]
755pub(crate) struct KwargsValues(ValueMap);
756
757impl Deref for KwargsValues {
758    type Target = ValueMap;
759
760    fn deref(&self) -> &Self::Target {
761        &self.0
762    }
763}
764
765impl Object for KwargsValues {
766    fn get_value(self: &Arc<Self>, key: &Value) -> Option<Value> {
767        self.0.get(key).cloned()
768    }
769
770    fn enumerate(self: &Arc<Self>) -> Enumerator {
771        self.mapped_enumerator(|this| Box::new(this.0.keys().cloned()))
772    }
773
774    fn enumerator_len(self: &Arc<Self>) -> Option<usize> {
775        Some(self.0.len())
776    }
777}
778
779impl<'a> ArgType<'a> for Kwargs {
780    type Output = Self;
781
782    fn from_value(value: Option<&'a Value>) -> Result<Self, Error> {
783        match value {
784            Some(value) => {
785                Kwargs::extract(value).ok_or_else(|| Error::from(ErrorKind::MissingArgument))
786            }
787            None => Ok(Kwargs::new(Default::default())),
788        }
789    }
790
791    fn from_state_and_values(
792        _state: Option<&'a State>,
793        values: &'a [Value],
794        offset: usize,
795    ) -> Result<(Self, usize), Error> {
796        let args = values
797            .get(offset)
798            .and_then(Kwargs::extract)
799            .map(|kwargs| (kwargs, 1))
800            .unwrap_or_else(|| (Kwargs::new(Default::default()), 0));
801
802        Ok(args)
803    }
804
805    fn is_trailing() -> bool {
806        true
807    }
808}
809
810impl Kwargs {
811    fn new(map: Arc<KwargsValues>) -> Kwargs {
812        Kwargs {
813            values: map,
814            used: RefCell::new(HashSet::new()),
815        }
816    }
817
818    /// Given a value, extracts the kwargs if there are any.
819    pub(crate) fn extract(value: &Value) -> Option<Kwargs> {
820        value
821            .as_object()
822            .and_then(|x| x.downcast::<KwargsValues>())
823            .map(Kwargs::new)
824    }
825
826    /// Wraps a value map into kwargs.
827    pub(crate) fn wrap(map: ValueMap) -> Value {
828        Value::from_object(KwargsValues(map))
829    }
830
831    /// Get a single argument from the kwargs but don't mark it as used.
832    pub fn peek<'a, T>(&'a self, key: &'a str) -> Result<T, Error>
833    where
834        T: ArgType<'a, Output = T>,
835    {
836        T::from_value(self.values.get(&Value::from(key))).map_err(|mut err| {
837            if err.kind() == ErrorKind::MissingArgument && err.detail().is_none() {
838                err.set_detail(format!("missing keyword argument '{}'", key));
839            }
840            err
841        })
842    }
843
844    /// Gets a single argument from the kwargs and marks it as used.
845    ///
846    /// This method works pretty much like [`from_args`] and marks any parameter
847    /// used internally.  For optional arguments you would typically use
848    /// `Option<T>` and for non optional ones directly `T`.
849    ///
850    /// Examples:
851    ///
852    /// ```
853    /// # use minijinja::Error;
854    /// # use minijinja::value::Kwargs; fn f(kwargs: Kwargs) -> Result<(), Error> {
855    /// // f(int=42) -> Some(42)
856    /// // f() -> None
857    /// let optional_int: Option<u32> = kwargs.get("int")?;
858    /// // f(int=42) -> 42
859    /// // f() -> Error
860    /// let required_int: u32 = kwargs.get("int")?;
861    /// # Ok(()) }
862    /// ```
863    ///
864    /// If you don't want to mark it as used, us [`peek`](Self::peek) instead.
865    pub fn get<'a, T>(&'a self, key: &'a str) -> Result<T, Error>
866    where
867        T: ArgType<'a, Output = T>,
868    {
869        let rv = ok!(self.peek::<T>(key));
870        self.used.borrow_mut().insert(key.to_string());
871        Ok(rv)
872    }
873
874    /// Checks if a keyword argument exists.
875    pub fn has(&self, key: &str) -> bool {
876        self.values.contains_key(&Value::from(key))
877    }
878
879    /// Iterates over all passed keyword arguments.
880    pub fn args(&self) -> impl Iterator<Item = &str> {
881        self.values.iter().filter_map(|x| x.0.as_str())
882    }
883
884    /// Asserts that all kwargs were used.
885    pub fn assert_all_used(&self) -> Result<(), Error> {
886        let used = self.used.borrow();
887        for key in self.values.keys() {
888            if let Some(key) = key.as_str() {
889                if !used.contains(key) {
890                    return Err(Error::new(
891                        ErrorKind::TooManyArguments,
892                        format!("unknown keyword argument '{}'", key),
893                    ));
894                }
895            } else {
896                return Err(Error::new(
897                    ErrorKind::InvalidOperation,
898                    "non string keys passed to kwargs",
899                ));
900            }
901        }
902        Ok(())
903    }
904}
905
906impl FromIterator<(String, Value)> for Kwargs {
907    fn from_iter<T>(iter: T) -> Self
908    where
909        T: IntoIterator<Item = (String, Value)>,
910    {
911        Kwargs::new(Arc::new(KwargsValues(
912            iter.into_iter().map(|(k, v)| (Value::from(k), v)).collect(),
913        )))
914    }
915}
916
917impl<'a> FromIterator<(&'a str, Value)> for Kwargs {
918    fn from_iter<T>(iter: T) -> Self
919    where
920        T: IntoIterator<Item = (&'a str, Value)>,
921    {
922        Kwargs::new(Arc::new(KwargsValues(
923            iter.into_iter().map(|(k, v)| (Value::from(k), v)).collect(),
924        )))
925    }
926}
927
928impl From<Kwargs> for Value {
929    fn from(value: Kwargs) -> Self {
930        Value::from_dyn_object(value.values)
931    }
932}
933
934impl TryFrom<Value> for Kwargs {
935    type Error = Error;
936
937    fn try_from(value: Value) -> Result<Self, Self::Error> {
938        match value.0 {
939            ValueRepr::Undefined(_) => Ok(Kwargs::new(Default::default())),
940            ValueRepr::Object(_) => {
941                Kwargs::extract(&value).ok_or_else(|| Error::from(ErrorKind::InvalidOperation))
942            }
943            _ => Err(Error::from(ErrorKind::InvalidOperation)),
944        }
945    }
946}
947
948impl<'a> ArgType<'a> for Value {
949    type Output = Self;
950
951    fn from_value(value: Option<&'a Value>) -> Result<Self, Error> {
952        match value {
953            Some(value) => Ok(value.clone()),
954            None => Err(Error::from(ErrorKind::MissingArgument)),
955        }
956    }
957
958    fn from_value_owned(value: Value) -> Result<Self, Error> {
959        Ok(value)
960    }
961}
962
963impl<'a> ArgType<'a> for String {
964    type Output = Self;
965
966    fn from_value(value: Option<&'a Value>) -> Result<Self, Error> {
967        match value {
968            Some(value) => {
969                if value.is_kwargs() {
970                    return Err(Error::new(
971                        ErrorKind::InvalidOperation,
972                        "cannot convert kwargs to string",
973                    ));
974                }
975                Ok(value.to_string())
976            }
977            None => Err(Error::from(ErrorKind::MissingArgument)),
978        }
979    }
980
981    fn from_value_owned(value: Value) -> Result<Self, Error> {
982        Ok(value.to_string())
983    }
984}
985
986impl<'a, T: ArgType<'a, Output = T>> ArgType<'a> for Vec<T> {
987    type Output = Vec<T>;
988
989    fn from_value(value: Option<&'a Value>) -> Result<Self, Error> {
990        match value {
991            None => Ok(Vec::new()),
992            Some(value) => {
993                let iter = ok!(value
994                    .as_object()
995                    .filter(|x| matches!(x.repr(), ObjectRepr::Seq | ObjectRepr::Iterable))
996                    .and_then(|x| x.try_iter())
997                    .ok_or_else(|| { Error::new(ErrorKind::InvalidOperation, "not iterable") }));
998                let mut rv = Vec::new();
999                for value in iter {
1000                    rv.push(ok!(T::from_value_owned(value)));
1001                }
1002                Ok(rv)
1003            }
1004        }
1005    }
1006
1007    fn from_value_owned(value: Value) -> Result<Self, Error> {
1008        let iter = ok!(value
1009            .as_object()
1010            .filter(|x| matches!(x.repr(), ObjectRepr::Seq | ObjectRepr::Iterable))
1011            .and_then(|x| x.try_iter())
1012            .ok_or_else(|| { Error::new(ErrorKind::InvalidOperation, "not iterable") }));
1013        let mut rv = Vec::new();
1014        for value in iter {
1015            rv.push(ok!(T::from_value_owned(value)));
1016        }
1017        Ok(rv)
1018    }
1019}
1020
1021impl<'a> ArgType<'a> for DynObject {
1022    type Output = Self;
1023
1024    fn from_value(value: Option<&'a Value>) -> Result<Self, Error> {
1025        value
1026            .ok_or_else(|| Error::from(ErrorKind::MissingArgument))
1027            .and_then(|v| Self::from_value_owned(v.clone()))
1028    }
1029
1030    fn from_value_owned(value: Value) -> Result<Self, Error> {
1031        value
1032            .as_object()
1033            .cloned()
1034            .ok_or_else(|| Error::new(ErrorKind::InvalidOperation, "not an object"))
1035    }
1036}
1037
1038impl From<Value> for String {
1039    fn from(val: Value) -> Self {
1040        val.to_string()
1041    }
1042}
1043
1044impl From<usize> for Value {
1045    fn from(val: usize) -> Self {
1046        Value::from(val as u64)
1047    }
1048}
1049
1050impl From<isize> for Value {
1051    fn from(val: isize) -> Self {
1052        Value::from(val as i64)
1053    }
1054}
1055
1056impl<I: Into<Value>> From<Option<I>> for Value {
1057    fn from(value: Option<I>) -> Self {
1058        match value {
1059            Some(value) => value.into(),
1060            None => Value::from(()),
1061        }
1062    }
1063}
1064
1065#[cfg(test)]
1066mod tests {
1067    use super::*;
1068
1069    #[test]
1070    fn test_as_f64() {
1071        let v = Value::from(42u32);
1072        let f: f64 = v.try_into().unwrap();
1073        assert_eq!(f, 42.0);
1074        let v = Value::from(42.5);
1075        let f: f64 = v.try_into().unwrap();
1076        assert_eq!(f, 42.5);
1077    }
1078
1079    #[test]
1080    fn test_split_kwargs() {
1081        let args = [
1082            Value::from(42),
1083            Value::from(true),
1084            Value::from(Kwargs::from_iter([
1085                ("foo", Value::from(1)),
1086                ("bar", Value::from(2)),
1087            ])),
1088        ];
1089        let (args, kwargs) = from_args::<(&[Value], Kwargs)>(&args).unwrap();
1090        assert_eq!(args, &[Value::from(42), Value::from(true)]);
1091        assert_eq!(kwargs.get::<Value>("foo").unwrap(), Value::from(1));
1092        assert_eq!(kwargs.get::<Value>("bar").unwrap(), Value::from(2));
1093    }
1094
1095    #[test]
1096    fn test_kwargs_fails_string_conversion() {
1097        let kwargs = Kwargs::from_iter([("foo", Value::from(1)), ("bar", Value::from(2))]);
1098        let args = [Value::from(kwargs)];
1099
1100        let result = from_args::<(String,)>(&args);
1101        assert!(result.is_err());
1102        assert_eq!(
1103            result.unwrap_err().to_string(),
1104            "invalid operation: cannot convert kwargs to string"
1105        );
1106
1107        let result = from_args::<(Cow<str>,)>(&args);
1108        assert!(result.is_err());
1109        assert_eq!(
1110            result.unwrap_err().to_string(),
1111            "invalid operation: cannot convert kwargs to string"
1112        );
1113    }
1114
1115    #[test]
1116    fn test_optional_none() {
1117        let (one,) = from_args::<(Option<i32>,)>(args!(None::<i32>)).unwrap();
1118        assert!(one.is_none());
1119        let (one,) = from_args::<(Option<i32>,)>(args!(Some(Value::UNDEFINED))).unwrap();
1120        assert!(one.is_none());
1121    }
1122}