1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
// SPDX-License-Identifier: Apache-2.0
#![warn(missing_docs)]
//! Expressions evaluation context.
//!
use crate::{ExtDataType, FnInfo, MyError, add_builtins, crs::CRS};
use core::fmt;
use std::{any::Any, collections::HashMap, rc::Rc};
/// A _Context_ object we will be handing to [evaluators][crate::Evaluator] so they are aware of
/// external registered _Functions_.
pub struct Context {
crs: CRS,
pub(crate) functions: HashMap<String, FnInfo>,
}
impl fmt::Debug for Context {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Context")
.field("crs", &self.crs)
.field("functions", &self.functions)
.finish()
}
}
impl Default for Context {
fn default() -> Self {
Self::new()
}
}
impl Context {
/// Create a new instance w/ no registered functions and the globally
/// configured implicit CRS.
pub fn new() -> Self {
Context {
crs: CRS::default(),
functions: HashMap::with_capacity(5),
}
}
/// Create a new instance w/ an implicit CRS specified by a given code.
/// Use this method to override the global default CRS code configured by
/// setting the environment variable `DEFAULT_CRS`.
pub fn try_with_crs(crs_code: &str) -> Result<Self, MyError> {
let mut result = Self::new();
result.crs = CRS::new(crs_code)?;
Ok(result)
}
/// Register a Function (Rust Closure) by name with expected argument(s)
/// and result types.
pub fn register<F>(
&mut self,
name: &str,
arg_types: Vec<ExtDataType>,
result_type: ExtDataType,
closure: F,
) where
F: Fn(Vec<Box<dyn Any>>) -> Option<Box<dyn Any>> + Send + Sync + 'static,
{
self.functions.insert(
name.to_string(),
FnInfo {
closure: Box::new(closure),
arg_types,
result_type,
},
);
}
/// Return a safe share-able read-only version of this frozen at the time
/// of the call.
pub fn freeze(self) -> SharedContext {
Rc::new(self)
}
/// Return a reference to the currently set CRS w/in this.
pub fn crs(&self) -> &CRS {
&self.crs
}
/// Return meta-information about a Function already registered in this.
pub fn fn_info(&self, name: &str) -> Option<&FnInfo> {
self.functions.get(name)
}
/// Register all builtin functions we support.
pub fn register_builtins(&mut self) {
add_builtins(self);
}
}
/// What we share between [Evaluator][crate::Evaluator]s.
pub type SharedContext = Rc<Context>;