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(¶meters))
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(¶meters));
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(¶meters))
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(¶meters);
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(¶meters);
199 assert!(max_count.is_none());
200 }
201}