1use std::ops::{Add, Sub, Mul, Div, Rem};
2use std::collections::HashMap;
3
4use lazy_static::lazy_static;
5
6use crate::arg::Arg;
7
8pub type Func = fn(Vec<Arg>) -> Arg;
9
10#[derive(Clone, Debug, PartialEq, PartialOrd)]
12pub struct Op {
13 pub name: String,
14 pub func: Func,
15}
16
17impl Op {
25 pub fn new(name: &str, func: Func) -> Op {
27 Op {
28 name: name.to_owned(),
29 func: func,
30 }
31 }
32
33 pub fn get(name: &str) -> Option<&Op> {
35 OPS.get(name)
36 }
37}
38
39macro_rules! register_builtin {
51 ( $($alias:tt => $func:tt),* $(,)? ) => {
52 lazy_static! {
53 static ref OPS: HashMap<&'static str, Op> = {
55 let mut map = HashMap::new();
56 $(
57 map.insert($alias, Op::new($alias, $func as Func));
58 map.insert(stringify!($func), Op::new(stringify!($func), $func as Func));
59 )*
60 map
61 };
62 }
63 };
64}
65
66register_builtin!(
67 "var" => var,
68
69 "=" => eq,
71 "<" => lt,
72 "<=" => le,
73 "!=" => ne,
74 ">=" => ge,
75 ">=" => ge,
76 ">" => gt,
77 "&" => and,
78 "&&" => and,
79 "all" => and,
80 "|" => or,
81 "||" => or,
82 "any" => or,
83 "!" => not,
84
85 "+" => add,
87 "sum" => add,
88 "-" => sub,
89 "minus" => sub,
90 "neg" => neg,
91 "*" => mul,
92 "/" => div,
93 "%" => rem,
94 "mod" => rem,
95 "abs" => abs,
96
97 "in" => r#in,
99 "startswith" => startswith,
100 "endswith" => endswith,
101 "split" => split,
102 "join" => join,
103
104 "lower" => lower,
106 "upper" => upper,
107 "match" => r#match,
108 "regex" => regex,
109
110 "num" => num,
112 "string" => string,
113);
114
115pub fn var(args: Vec<Arg>) -> Arg {
117 args[0].clone()
118}
119
120pub fn eq(args: Vec<Arg>) -> Arg {
121 Arg::Bool(args.windows(2).all(|w| w[0] == w[1]))
122}
123
124pub fn lt(args: Vec<Arg>) -> Arg {
135 Arg::Bool(args.windows(2).all(|w| w[0] < w[1]))
136}
137
138pub fn le(args: Vec<Arg>) -> Arg {
139 Arg::Bool(args.windows(2).all(|w| w[0] <= w[1]))
140}
141
142pub fn ne(args: Vec<Arg>) -> Arg {
143 Arg::Bool(args.windows(2).all(|w| w[0] != w[1]))
144}
145
146pub fn ge(args: Vec<Arg>) -> Arg {
147 Arg::Bool(args.windows(2).all(|w| w[0] >= w[1]))
148}
149
150pub fn gt(args: Vec<Arg>) -> Arg {
151 Arg::Bool(args.windows(2).all(|w| w[0] > w[1]))
152}
153
154pub fn and(args: Vec<Arg>) -> Arg {
155 Arg::Bool(args.iter().all(|v| v.into()))
156}
157
158pub fn or(args: Vec<Arg>) -> Arg {
159 Arg::Bool(args.iter().any(|v| v.into()))
160}
161
162pub fn not(args: Vec<Arg>) -> Arg {
163 let b: bool = args.get(0).unwrap_or(&Arg::Null).into();
164 Arg::Bool(!b)
165}
166
167pub fn add(args: Vec<Arg>) -> Arg {
168 let mut it = args.into_iter();
169 it.next().map(|first| it.fold(first, Add::add)).unwrap_or(Arg::Null)
170}
171
172pub fn sub(args: Vec<Arg>) -> Arg {
173 let mut it = args.into_iter();
174 it.next().map(|first| it.fold(first, Sub::sub)).unwrap_or(Arg::Null)
175}
176
177pub fn neg(args: Vec<Arg>) -> Arg {
178 -args.get(0).unwrap_or(&Arg::Null)
179}
180
181pub fn mul(args: Vec<Arg>) -> Arg {
182 let mut it = args.into_iter();
183 it.next().map(|first| it.fold(first, Mul::mul)).unwrap_or(Arg::Null)
184}
185
186pub fn div(args: Vec<Arg>) -> Arg {
187 let mut it = args.into_iter();
188 it.next().map(|first| it.fold(first, Div::div)).unwrap_or(Arg::Null)
189}
190
191pub fn rem(args: Vec<Arg>) -> Arg {
194 let mut it = args.into_iter();
195 it.next().map(|first| it.fold(first, Rem::rem)).unwrap_or(Arg::Null)
196}
197
198pub fn abs(args: Vec<Arg>) -> Arg {
200 let int: i64 = args.get(0).unwrap_or(&Arg::Null).into();
201 Arg::Int(int.abs())
202}
203
204pub fn r#in(args: Vec<Arg>) -> Arg {
211 Arg::Bool(args[1..].contains(&args[0]))
212}
213
214pub fn startswith(args: Vec<Arg>) -> Arg {
222 let ret = match &args[0] {
223 Arg::String(s) => Arg::Bool((&s).starts_with(&args[1].to_string())),
224 Arg::Array(a) => Arg::Bool(a.starts_with(&args[1..])),
225 _ => Arg::Bool(false),
226 };
227 ret
228}
229
230pub fn endswith(args: Vec<Arg>) -> Arg {
238 let ret = match &args[0] {
239 Arg::String(s) => Arg::Bool((&s).ends_with(&args[1].to_string())),
240 Arg::Array(a) => Arg::Bool(a.ends_with(&args[1..])),
241 _ => Arg::Bool(false),
242 };
243 ret
244}
245
246pub fn lower(args: Vec<Arg>) -> Arg {
253 Arg::String(String::from(&args[0]).to_lowercase())
254}
255
256pub fn upper(args: Vec<Arg>) -> Arg {
263 Arg::String(String::from(&args[0]).to_uppercase())
264}
265
266pub fn split(args: Vec<Arg>) -> Arg {
273 let s = &String::from(&args[0]);
274 let sep = &String::from(&args[1]);
275 Arg::Array(s.split(sep).map(|x| Arg::String(x.to_owned())).collect())
276}
277
278pub fn join(args: Vec<Arg>) -> Arg {
285 let mut it = args.into_iter();
286 let sep = &String::from(&it.nth(0).unwrap_or(Arg::String("".to_owned())));
287 Arg::String(it.map(|x| String::from(&x)).collect::<Vec<String>>().join(sep))
288}
289
290pub fn r#match(args: Vec<Arg>) -> Arg {
297 match glob::Pattern::new(&String::from(&args[1])) {
298 Ok(patt) => {
299 Arg::Bool(patt.matches(&String::from(&args[0])))
300 },
301 Err(_) => Arg::Bool(false),
302 }
303}
304
305pub fn regex(args: Vec<Arg>) -> Arg {
312 match regex::Regex::new(&String::from(&args[1])) {
313 Ok(re) => {
314 Arg::Bool(re.is_match(&String::from(&args[0])))
315 },
316 Err(_) => Arg::Bool(false),
317 }
318}
319
320pub fn num(args: Vec<Arg>) -> Arg {
329 let a = args[0].clone();
330 match a {
331 Arg::Int(_) => a,
332 Arg::Float(_) => a,
333 Arg::String(v) => {
334 match v.parse::<i64>() {
335 Ok(i) => Arg::Int(i),
336 Err(_) => match v.parse::<f64>() {
337 Ok(f) => Arg::Float(f),
338 Err(_) => Arg::Int(0i64),
339 }
340 }
341 },
342 _ => Arg::Int(Into::<i64>::into(a)),
343 }
344}
345
346pub fn string(args: Vec<Arg>) -> Arg {
353 Arg::String(String::from(&args[0]))
354}
355
356