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