Skip to main content

ogc_cql2/
context.rs

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