xee_interpreter/context/
static_context.rs1use std::cell::RefCell;
2use std::fmt::Debug;
3use std::rc::Rc;
4use std::sync::LazyLock;
5
6use iri_string::types::IriAbsoluteStr;
7use iri_string::types::IriAbsoluteString;
8use iri_string::types::IriReferenceStr;
9use xee_name::{Namespaces, VariableNames};
10use xee_xpath_ast::ast;
11use xee_xpath_ast::XPathParserContext;
12
13use crate::error;
14use crate::function;
15use crate::string::{Collation, Collations};
16
17static STATIC_FUNCTIONS: LazyLock<function::StaticFunctions> =
18 LazyLock::new(function::StaticFunctions::new);
19
20static DEFAULT_COLLATION: LazyLock<IriAbsoluteString> = LazyLock::new(|| {
22 "http://www.w3.org/2005/xpath-functions/collation/codepoint"
23 .try_into()
24 .unwrap()
25});
26
27#[derive(Debug)]
28pub struct StaticContext {
29 parser_context: XPathParserContext,
30 functions: &'static function::StaticFunctions,
31 collations: RefCell<Collations>,
33 static_base_uri: Option<IriAbsoluteString>,
34}
35
36impl Default for StaticContext {
37 fn default() -> Self {
38 Self::new(Namespaces::default(), VariableNames::default(), None)
39 }
40}
41
42impl From<XPathParserContext> for StaticContext {
43 fn from(parser_context: XPathParserContext) -> Self {
44 Self {
45 parser_context,
46 functions: &STATIC_FUNCTIONS,
47 collations: RefCell::new(Collations::new()),
48 static_base_uri: None,
49 }
50 }
51}
52
53impl StaticContext {
54 pub(crate) fn new(
55 namespaces: Namespaces,
56 variable_names: VariableNames,
57 static_base_uri: Option<IriAbsoluteString>,
58 ) -> Self {
59 Self {
60 parser_context: XPathParserContext::new(namespaces, variable_names),
61 functions: &STATIC_FUNCTIONS,
62 collations: RefCell::new(Collations::new()),
63 static_base_uri,
64 }
65 }
66
67 pub fn from_namespaces(namespaces: Namespaces) -> Self {
68 Self::new(namespaces, VariableNames::default(), None)
69 }
70
71 pub fn namespaces(&self) -> &Namespaces {
72 &self.parser_context.namespaces
73 }
74
75 pub fn variable_names(&self) -> &VariableNames {
76 &self.parser_context.variable_names
77 }
78
79 pub fn default_collation(&self) -> error::Result<Rc<Collation>> {
80 self.collation(self.default_collation_uri())
81 }
82
83 pub fn default_collation_uri(&self) -> &IriReferenceStr {
84 DEFAULT_COLLATION.as_ref()
85 }
86
87 pub(crate) fn resolve_collation_str(
88 &self,
89 collation: Option<&str>,
90 ) -> error::Result<Rc<Collation>> {
91 let collation: Option<&IriReferenceStr> = if let Some(collation) = collation {
92 collation.try_into().ok()
93 } else {
94 None
95 };
96 self.collation(collation.unwrap_or(self.default_collation_uri()))
97 }
98
99 pub fn static_base_uri(&self) -> Option<&IriAbsoluteStr> {
100 self.static_base_uri.as_deref()
101 }
102
103 pub(crate) fn collation(&self, uri: &IriReferenceStr) -> error::Result<Rc<Collation>> {
104 self.collations
105 .borrow_mut()
106 .load(self.static_base_uri(), uri)
107 }
108
109 pub fn parse_xpath(&self, s: &str) -> Result<ast::XPath, xee_xpath_ast::ParserError> {
114 self.parser_context.parse_xpath(s)
115 }
116
117 pub fn parse_value_template_xpath(
120 &self,
121 s: &str,
122 ) -> Result<ast::XPath, xee_xpath_ast::ParserError> {
123 self.parser_context.parse_value_template_xpath(s)
124 }
125
126 pub fn function_by_id(
128 &self,
129 static_function_id: function::StaticFunctionId,
130 ) -> &function::StaticFunction {
131 self.functions.get_by_index(static_function_id)
132 }
133
134 pub fn function_id_by_name(
136 &self,
137 name: &xot::xmlname::OwnedName,
138 arity: u8,
139 ) -> Option<function::StaticFunctionId> {
140 self.functions.get_by_name(name, arity)
141 }
142
143 pub fn function_id_by_internal_name(
145 &self,
146 name: &xot::xmlname::OwnedName,
147 arity: u8,
148 ) -> Option<function::StaticFunctionId> {
149 self.functions.get_by_internal_name(name, arity)
150 }
151}