1use std::collections::HashMap;
4
5use crate::Expression;
6use crate::JmespathError;
7use crate::functions::*;
8use crate::parse;
9use crate::registry::{Category, FunctionRegistry};
10
11pub struct Runtime {
13 functions: HashMap<String, Box<dyn Function>>,
14}
15
16impl Default for Runtime {
17 fn default() -> Self {
18 Runtime {
19 functions: HashMap::with_capacity(26),
20 }
21 }
22}
23
24impl Runtime {
25 pub fn new() -> Runtime {
27 Default::default()
28 }
29
30 pub fn strict() -> Runtime {
32 let mut rt = Runtime::new();
33 rt.register_builtin_functions();
34 rt
35 }
36
37 pub fn builder() -> RuntimeBuilder {
39 RuntimeBuilder::new()
40 }
41
42 #[inline]
44 pub fn compile<'a>(&'a self, expression: &str) -> Result<Expression<'a>, JmespathError> {
45 parse(expression).map(|ast| Expression::new(expression, ast, self))
46 }
47
48 #[inline]
50 pub fn register_function(&mut self, name: &str, f: Box<dyn Function>) {
51 self.functions.insert(name.to_owned(), f);
52 }
53
54 pub fn deregister_function(&mut self, name: &str) -> Option<Box<dyn Function>> {
56 self.functions.remove(name)
57 }
58
59 #[inline]
61 pub fn get_function<'a>(&'a self, name: &str) -> Option<&'a dyn Function> {
62 self.functions.get(name).map(AsRef::as_ref)
63 }
64
65 pub fn function_names(&self) -> impl Iterator<Item = &str> {
67 self.functions.keys().map(|s| s.as_str())
68 }
69
70 pub fn register_builtin_functions(&mut self) {
72 self.register_function("abs", Box::new(AbsFn::new()));
73 self.register_function("avg", Box::new(AvgFn::new()));
74 self.register_function("ceil", Box::new(CeilFn::new()));
75 self.register_function("contains", Box::new(ContainsFn::new()));
76 self.register_function("ends_with", Box::new(EndsWithFn::new()));
77 self.register_function("floor", Box::new(FloorFn::new()));
78 self.register_function("join", Box::new(JoinFn::new()));
79 self.register_function("keys", Box::new(KeysFn::new()));
80 self.register_function("length", Box::new(LengthFn::new()));
81 self.register_function("map", Box::new(MapFn::new()));
82 self.register_function("min", Box::new(MinFn::new()));
83 self.register_function("max", Box::new(MaxFn::new()));
84 self.register_function("max_by", Box::new(MaxByFn::new()));
85 self.register_function("min_by", Box::new(MinByFn::new()));
86 self.register_function("merge", Box::new(MergeFn::new()));
87 self.register_function("not_null", Box::new(NotNullFn::new()));
88 self.register_function("reverse", Box::new(ReverseFn::new()));
89 self.register_function("sort", Box::new(SortFn::new()));
90 self.register_function("sort_by", Box::new(SortByFn::new()));
91 self.register_function("starts_with", Box::new(StartsWithFn::new()));
92 self.register_function("sum", Box::new(SumFn::new()));
93 self.register_function("to_array", Box::new(ToArrayFn::new()));
94 self.register_function("to_number", Box::new(ToNumberFn::new()));
95 self.register_function("to_string", Box::new(ToStringFn::new()));
96 self.register_function("type", Box::new(TypeFn::new()));
97 self.register_function("values", Box::new(ValuesFn::new()));
98 }
99}
100
101pub struct RuntimeBuilder {
116 registry: FunctionRegistry,
117 include_standard: bool,
118}
119
120impl RuntimeBuilder {
121 fn new() -> Self {
122 RuntimeBuilder {
123 registry: FunctionRegistry::new(),
124 include_standard: false,
125 }
126 }
127
128 pub fn with_standard(mut self) -> Self {
130 self.include_standard = true;
131 self
132 }
133
134 pub fn with_category(mut self, category: Category) -> Self {
136 self.registry.register_category(category);
137 self
138 }
139
140 pub fn with_all_extensions(mut self) -> Self {
142 self.registry.register_all();
143 self
144 }
145
146 pub fn without_function(mut self, name: &str) -> Self {
148 self.registry.disable_function(name);
149 self
150 }
151
152 pub fn build(self) -> Runtime {
154 let mut rt = Runtime::new();
155 if self.include_standard {
156 rt.register_builtin_functions();
157 }
158 self.registry.apply(&mut rt);
159 rt
160 }
161}