jmespath_community/functions/
signature.rs

1use super::types::DataType;
2
3/// Represents the type for a parameter to a JMESPath [`super::Function`].
4#[derive(Debug)]
5pub enum ParamTypes {
6    /// Represents a parameter of a given [`crate::functions::DataType`].
7    /// # Example
8    /// ```
9    /// use jmespath_community as jmespath;
10    /// use jmespath::functions::DataType;
11    /// use jmespath::functions::Parameter::*;
12    /// use jmespath::functions::ParamTypes::*;
13    /// let data_types = Optional(Of(DataType::String));
14    /// ```
15    ///
16    /// See [`crate::functions::Parameter`].
17    Of(DataType),
18    /// Represents a parameter whose [`crate::functions::DataType`] is taken from a list.
19    /// # Example
20    /// ```
21    /// use jmespath_community as jmespath;
22    /// use jmespath::functions::DataType;
23    /// use jmespath::functions::Parameter::*;
24    /// use jmespath::functions::ParamTypes::*;
25    /// let data_types = Required(Any(vec![DataType::Array, DataType::Object, DataType::String]));
26    /// ```
27    ///
28    /// See [`crate::functions::Parameter`].
29    Any(Vec<DataType>),
30}
31
32/// Represents the definition for a parameter to a JMESPath [`super::Function`].
33///
34#[derive(Debug)]
35pub enum Parameter {
36    /// Represents a required parameter to a JMESPath [`super::Function`].
37    ///
38    /// # Example
39    /// See [ParamTypes](crate::functions::ParamTypes).
40    Required(ParamTypes),
41    /// Represents an optional parameter to a JMESPath [`super::Function`].
42    ///
43    /// An optional parameter MAY be present in the last parameters from
44    /// a given function signature and MUST be followed by zero or more
45    /// optional parameters.
46    ///
47    /// # Example
48    /// See [ParamTypes](crate::functions::ParamTypes).
49    Optional(ParamTypes),
50    /// Represents a variadic parameter to a JMESPath [`super::Function`].
51    ///
52    /// A variadic parameter MAY be present as the last parameter from
53    /// a given function signature.
54    ///
55    /// # Example
56    /// ```
57    /// use jmespath_community as jmespath;
58    /// use jmespath::functions::DataType;
59    /// use jmespath::functions::Parameter::*;
60    /// use jmespath::functions::ParamTypes::*;
61    /// let data_types = Variadic(Of(DataType::String));
62    /// ```
63    Variadic(ParamTypes),
64}
65
66impl Parameter {
67    /// Returns `true` if the parameter is [`Optional`].
68    ///
69    /// [`Optional`]: Parameter::Optional
70    #[must_use]
71    pub fn is_optional(&self) -> bool {
72        matches!(self, Self::Optional(..))
73    }
74    /// Returns `true` if the parameter is [`Variadic`].
75    ///
76    /// [`Variadic`]: Parameter::Variadic
77    #[must_use]
78    pub fn is_variadic(&self) -> bool {
79        matches!(self, Self::Variadic(..))
80    }
81    pub fn get_data_type(&self) -> Option<DataType> {
82        let param_types = self.get_param_types();
83        match param_types {
84            ParamTypes::Of(t) => Some(*t),
85            _ => None,
86        }
87    }
88    pub fn get_data_types(&self) -> Option<&Vec<DataType>> {
89        let param_types = self.get_param_types();
90        match param_types {
91            ParamTypes::Any(t) => Some(t),
92            _ => None,
93        }
94    }
95    pub fn get_param_types(&self) -> &ParamTypes {
96        match self {
97            Parameter::Required(t) => t,
98            Parameter::Optional(t) => t,
99            Parameter::Variadic(t) => t,
100        }
101    }
102}
103
104/// Helper functions for dealing with JMESPath [`super::Function`] signatures.
105pub struct Signature {}
106impl Signature {
107    /// Returns true if the signature is variadic, _i.e_ if the
108    /// last parameter may be repeated an arbitrary number of times.
109    ///
110    /// # Example
111    ///
112    /// ```
113    /// use jmespath_community as jmespath;
114    /// use jmespath::functions::DataType::*;
115    /// use jmespath::functions::Parameter::*;
116    /// use jmespath::functions::ParamTypes::*;
117    /// use jmespath::functions::Signature;
118    ///
119    /// let variadic = vec![Required(Of(Number)), Variadic(Of(String))];
120    /// assert!(Signature::is_variadic(&variadic));
121    /// ```
122    pub fn is_variadic(parameters: &Vec<Parameter>) -> bool {
123        match parameters.last() {
124            Some(param) => param.is_variadic(),
125            _ => false,
126        }
127    }
128    /// Returns the minimum number of required parameters.
129    ///
130    /// # Example
131    ///
132    /// ```
133    /// use jmespath_community as jmespath;
134    /// use jmespath::functions::DataType::*;
135    /// use jmespath::functions::Parameter::*;
136    /// use jmespath::functions::ParamTypes::*;
137    /// use jmespath::functions::Signature;
138    ///
139    /// let parameters = vec![Required(Of(Number))];
140    /// assert_eq!(1, Signature::get_min_args_count(&parameters))
141    /// ```
142    pub fn get_min_args_count(parameters: &Vec<Parameter>) -> usize {
143        parameters
144            .iter()
145            .filter(|x| {
146                matches!(x, Parameter::Required(..)) || matches!(x, Parameter::Variadic(..))
147            })
148            .count()
149    }
150    /// Returns te maximum number of required and optional parameters, if any.
151    ///
152    pub fn get_max_args_count(parameters: &Vec<Parameter>) -> Option<usize> {
153        if Self::is_variadic(parameters) {
154            return None;
155        }
156        Some(parameters.len())
157    }
158}
159
160#[cfg(test)]
161mod tests {
162
163    use super::*;
164
165    use super::DataType::*;
166    use super::ParamTypes::*;
167    use super::Parameter::*;
168
169    #[test]
170    fn is_variadic_false_on_empty_parameters_list() {
171        let no_parameters = vec![];
172        assert!(!Signature::is_variadic(&no_parameters));
173    }
174    #[test]
175    fn is_variadic_false_on_required_or_optional_parameters_list() {
176        let parameters = vec![Required(Of(Number)), Optional(Of(String))];
177        assert!(!Signature::is_variadic(&parameters));
178    }
179    #[test]
180    fn is_variadic() {
181        let variadic = vec![Required(Of(Number)), Variadic(Of(String))];
182        assert!(Signature::is_variadic(&variadic));
183    }
184    #[test]
185    fn get_min_args_count() {
186        let parameters = vec![Variadic(Of(Number))];
187        assert_eq!(1, Signature::get_min_args_count(&parameters))
188    }
189    #[test]
190    fn get_max_args_count() {
191        let parameters = vec![Required(Of(Number)), Optional(Of(Number))];
192        let max_count = Signature::get_max_args_count(&parameters);
193        assert!(matches!(max_count, Some(2)));
194    }
195    #[test]
196    fn get_max_args_count_is_none_for_variadic() {
197        let parameters = vec![Variadic(Of(Number))];
198        let max_count = Signature::get_max_args_count(&parameters);
199        assert!(max_count.is_none());
200    }
201}