1use std::collections::{HashMap, HashSet};
16use std::fmt;
17
18use lazy_static::lazy_static;
19
20use crate::parser::value::ValueType;
21use crate::parser::{Expr, Prettier};
22use crate::util::join_vector;
23
24#[derive(Debug, Clone, PartialEq, Eq)]
26pub struct FunctionArgs {
27 pub args: Vec<Box<Expr>>,
28}
29
30impl FunctionArgs {
31 pub fn empty_args() -> Self {
32 Self { args: vec![] }
33 }
34
35 pub fn new_args(expr: Expr) -> Self {
36 Self {
37 args: vec![Box::new(expr)],
38 }
39 }
40
41 pub fn append_args(mut self: FunctionArgs, expr: Expr) -> Self {
42 self.args.push(Box::new(expr));
43 self
44 }
45
46 pub fn is_empty(&self) -> bool {
47 self.args.is_empty()
48 }
49
50 pub fn len(&self) -> usize {
51 self.args.len()
52 }
53
54 pub fn first(&self) -> Option<Box<Expr>> {
55 self.args.first().cloned()
56 }
57
58 pub fn last(&self) -> Option<Box<Expr>> {
59 self.args.last().cloned()
60 }
61}
62
63impl fmt::Display for FunctionArgs {
64 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
65 write!(f, "{}", join_vector(&self.args, ", ", false))
66 }
67}
68
69impl Prettier for FunctionArgs {
70 fn pretty(&self, level: usize, max: usize) -> String {
71 let mut v = vec![];
72 for ex in &self.args {
73 v.push(ex.pretty(level, max));
74 }
75 v.join(",\n")
76 }
77}
78
79#[derive(Debug, Clone, PartialEq, Eq)]
81pub struct Function {
82 pub name: &'static str,
83 pub arg_types: Vec<ValueType>,
84 pub variadic: bool,
85 pub return_type: ValueType,
86}
87
88impl Function {
89 pub fn new(
90 name: &'static str,
91 arg_types: Vec<ValueType>,
92 variadic: bool,
93 return_type: ValueType,
94 ) -> Self {
95 Self {
96 name,
97 arg_types,
98 variadic,
99 return_type,
100 }
101 }
102}
103
104macro_rules! map {
105 ($(($name:literal, $arg:expr, $ret:expr)),*) => (
107 {
108 let mut m: HashMap<&'static str, Function> = HashMap::new();
109 $(
110 let variadic = FUNCTIONS_WITH_VARIADIC_ARGS.contains($name);
111 let func = Function::new($name, $arg, variadic, $ret);
112 m.insert($name, func);
113 )*
114 m
115 }
116 );
117}
118
119lazy_static! {
120 static ref FUNCTIONS_WITH_VARIADIC_ARGS: HashSet<&'static str> = HashSet::from([
121 "days_in_month",
122 "day_of_year",
123 "day_of_month",
124 "day_of_week",
125 "year",
126 "month",
127 "hour",
128 "minute",
129 "label_join",
130 "round",
131 ]);
132 static ref FUNCTIONS: HashMap<&'static str, Function> = map!(
133 ("abs", vec![ValueType::Vector], ValueType::Vector),
134 ("absent", vec![ValueType::Vector], ValueType::Vector),
135 (
136 "absent_over_time",
137 vec![ValueType::Matrix],
138 ValueType::Vector
139 ),
140 ("acos", vec![ValueType::Vector], ValueType::Vector),
141 ("acosh", vec![ValueType::Vector], ValueType::Vector),
142 ("asin", vec![ValueType::Vector], ValueType::Vector),
143 ("asinh", vec![ValueType::Vector], ValueType::Vector),
144 ("atan", vec![ValueType::Vector], ValueType::Vector),
145 ("atanh", vec![ValueType::Vector], ValueType::Vector),
146 ("avg_over_time", vec![ValueType::Matrix], ValueType::Vector),
147 ("ceil", vec![ValueType::Vector], ValueType::Vector),
148 ("changes", vec![ValueType::Matrix], ValueType::Vector),
149 (
150 "clamp",
151 vec![ValueType::Vector, ValueType::Scalar, ValueType::Scalar],
152 ValueType::Vector
153 ),
154 (
155 "clamp_max",
156 vec![ValueType::Vector, ValueType::Scalar],
157 ValueType::Vector
158 ),
159 (
160 "clamp_min",
161 vec![ValueType::Vector, ValueType::Scalar],
162 ValueType::Vector
163 ),
164 ("cos", vec![ValueType::Vector], ValueType::Vector),
165 ("cosh", vec![ValueType::Vector], ValueType::Vector),
166 (
167 "count_over_time",
168 vec![ValueType::Matrix],
169 ValueType::Vector
170 ),
171 ("days_in_month", vec![ValueType::Vector], ValueType::Vector),
172 ("day_of_month", vec![ValueType::Vector], ValueType::Vector),
173 ("day_of_week", vec![ValueType::Vector], ValueType::Vector),
174 ("day_of_year", vec![ValueType::Vector], ValueType::Vector),
175 ("deg", vec![ValueType::Vector], ValueType::Vector),
176 ("delta", vec![ValueType::Matrix], ValueType::Vector),
177 ("deriv", vec![ValueType::Matrix], ValueType::Vector),
178 ("exp", vec![ValueType::Vector], ValueType::Vector),
179 ("floor", vec![ValueType::Vector], ValueType::Vector),
180 (
181 "histogram_count",
182 vec![ValueType::Vector],
183 ValueType::Vector
184 ),
185 ("histogram_sum", vec![ValueType::Vector], ValueType::Vector),
186 (
187 "histogram_fraction",
188 vec![ValueType::Scalar, ValueType::Scalar, ValueType::Vector],
189 ValueType::Vector
190 ),
191 (
192 "histogram_quantile",
193 vec![ValueType::Scalar, ValueType::Vector],
194 ValueType::Vector
195 ),
196 (
197 "holt_winters",
198 vec![ValueType::Matrix, ValueType::Scalar, ValueType::Scalar],
199 ValueType::Vector
200 ),
201 ("hour", vec![ValueType::Vector], ValueType::Vector),
202 ("idelta", vec![ValueType::Matrix], ValueType::Vector),
203 ("increase", vec![ValueType::Matrix], ValueType::Vector),
204 ("irate", vec![ValueType::Matrix], ValueType::Vector),
205 (
206 "label_replace",
207 vec![
208 ValueType::Vector,
209 ValueType::String,
210 ValueType::String,
211 ValueType::String,
212 ValueType::String,
213 ],
214 ValueType::Vector
215 ),
216 (
217 "label_join",
218 vec![
219 ValueType::Vector,
220 ValueType::String,
221 ValueType::String,
222 ValueType::String,
223 ],
224 ValueType::Vector
225 ),
226 ("last_over_time", vec![ValueType::Matrix], ValueType::Vector),
227 ("ln", vec![ValueType::Vector], ValueType::Vector),
228 ("log10", vec![ValueType::Vector], ValueType::Vector),
229 ("log2", vec![ValueType::Vector], ValueType::Vector),
230 ("max_over_time", vec![ValueType::Matrix], ValueType::Vector),
231 ("min_over_time", vec![ValueType::Matrix], ValueType::Vector),
232 ("minute", vec![ValueType::Vector], ValueType::Vector),
233 ("month", vec![ValueType::Vector], ValueType::Vector),
234 ("pi", vec![], ValueType::Scalar),
235 (
236 "predict_linear",
237 vec![ValueType::Matrix, ValueType::Scalar],
238 ValueType::Vector
239 ),
240 (
241 "present_over_time",
242 vec![ValueType::Matrix],
243 ValueType::Vector
244 ),
245 (
246 "quantile_over_time",
247 vec![ValueType::Scalar, ValueType::Matrix],
248 ValueType::Vector
249 ),
250 ("rad", vec![ValueType::Vector], ValueType::Vector),
251 ("rate", vec![ValueType::Matrix], ValueType::Vector),
252 ("resets", vec![ValueType::Matrix], ValueType::Vector),
253 (
254 "round",
255 vec![ValueType::Vector, ValueType::Scalar],
256 ValueType::Vector
257 ),
258 ("scalar", vec![ValueType::Vector], ValueType::Scalar),
259 ("sgn", vec![ValueType::Vector], ValueType::Vector),
260 ("sin", vec![ValueType::Vector], ValueType::Vector),
261 ("sinh", vec![ValueType::Vector], ValueType::Vector),
262 ("sort", vec![ValueType::Vector], ValueType::Vector),
263 ("sort_desc", vec![ValueType::Vector], ValueType::Vector),
264 ("sqrt", vec![ValueType::Vector], ValueType::Vector),
265 (
266 "stddev_over_time",
267 vec![ValueType::Matrix],
268 ValueType::Vector
269 ),
270 (
271 "stdvar_over_time",
272 vec![ValueType::Matrix],
273 ValueType::Vector
274 ),
275 ("sum_over_time", vec![ValueType::Matrix], ValueType::Vector),
276 ("tan", vec![ValueType::Vector], ValueType::Vector),
277 ("tanh", vec![ValueType::Vector], ValueType::Vector),
278 ("time", vec![], ValueType::Scalar),
279 ("timestamp", vec![ValueType::Vector], ValueType::Vector),
280 ("vector", vec![ValueType::Scalar], ValueType::Vector),
281 ("year", vec![ValueType::Vector], ValueType::Vector)
282 );
283}
284
285pub(crate) fn get_function(name: &str) -> Option<Function> {
287 FUNCTIONS.get(name).cloned()
288}
289
290#[cfg(test)]
291mod tests {
292 use super::*;
293 use crate::parser::*;
294
295 #[test]
296 fn test_function_equality() {
297 let func = "month";
298 assert!(get_function(func).is_some());
299 assert_eq!(get_function(func), get_function(func));
300 }
301
302 #[test]
303 fn test_function_args_equality() {
304 assert_eq!(FunctionArgs::empty_args(), FunctionArgs::empty_args());
305
306 let arg1 = Expr::NumberLiteral(NumberLiteral::new(1.0));
307 let arg2 = Expr::StringLiteral(StringLiteral {
308 val: "prometheus".into(),
309 });
310 let args1 = FunctionArgs::new_args(arg1).append_args(arg2);
311
312 let arg1 = Expr::NumberLiteral(NumberLiteral::new(0.5 + 0.5));
313 let arg2 = Expr::StringLiteral(StringLiteral {
314 val: String::from("prometheus"),
315 });
316 let args2 = FunctionArgs::new_args(arg1).append_args(arg2);
317
318 assert_eq!(args1, args2);
319 }
320
321 #[test]
322 fn test_args_display() {
323 let cases = vec![
324 (
325 FunctionArgs::new_args(Expr::from(VectorSelector::from("up"))),
326 "up",
327 ),
328 (
329 FunctionArgs::empty_args()
330 .append_args(Expr::from("src1"))
331 .append_args(Expr::from("src2"))
332 .append_args(Expr::from("src3")),
333 r#""src1", "src2", "src3""#,
334 ),
335 ];
336
337 for (args, expect) in cases {
338 assert_eq!(expect, args.to_string())
339 }
340 }
341}