xee_interpreter/context/
dynamic_context.rs1use ahash::{AHashMap, HashMap};
2use iri_string::types::{IriStr, IriString};
3use std::fmt::Debug;
4
5use crate::function::{self, Function};
6use crate::{error::Error, interpreter::Program};
7use crate::{interpreter, sequence};
8
9use super::{DocumentsRef, StaticContext};
10
11pub type Variables = AHashMap<xot::xmlname::OwnedName, sequence::Sequence>;
17
18#[derive(Debug)]
20pub struct DynamicContext<'a> {
21 program: &'a Program,
23
24 context_item: Option<sequence::Item>,
26 documents: DocumentsRef,
30 variables: Variables,
31 current_datetime: chrono::DateTime<chrono::offset::FixedOffset>,
34 default_collection: Option<sequence::Sequence>,
36 collections: HashMap<IriString, sequence::Sequence>,
38 default_uri_collection: Option<sequence::Sequence>,
40 uri_collections: HashMap<IriString, sequence::Sequence>,
42 environment_variables: HashMap<String, String>,
44}
45
46impl<'a> DynamicContext<'a> {
47 #[allow(clippy::too_many_arguments)]
48 pub(crate) fn new(
49 program: &'a Program,
50 context_item: Option<sequence::Item>,
51 documents: DocumentsRef,
52 variables: Variables,
53 current_datetime: chrono::DateTime<chrono::offset::FixedOffset>,
54 default_collection: Option<sequence::Sequence>,
55 collections: HashMap<IriString, sequence::Sequence>,
56 default_uri_collection: Option<sequence::Sequence>,
57 uri_collections: HashMap<IriString, sequence::Sequence>,
58 environment_variables: HashMap<String, String>,
59 ) -> Self {
60 Self {
61 program,
62 context_item,
63 documents,
64 variables,
65 current_datetime,
66 default_collection,
67 collections,
68 default_uri_collection,
69 uri_collections,
70 environment_variables,
71 }
72 }
73
74 pub fn static_context(&self) -> &StaticContext {
76 self.program.static_context()
77 }
78
79 pub fn context_item(&self) -> Option<&sequence::Item> {
81 self.context_item.as_ref()
82 }
83
84 pub fn documents(&self) -> DocumentsRef {
86 self.documents.clone()
87 }
88
89 pub fn variables(&self) -> &Variables {
91 &self.variables
92 }
93
94 pub fn default_collection(&self) -> Option<&sequence::Sequence> {
96 self.default_collection.as_ref()
97 }
98
99 pub fn collection(&self, uri: &IriStr) -> Option<&sequence::Sequence> {
101 self.collections.get(uri)
102 }
103
104 pub fn default_uri_collection(&self) -> Option<&sequence::Sequence> {
106 self.default_uri_collection.as_ref()
107 }
108
109 pub fn uri_collection(&self, uri: &IriStr) -> Option<&sequence::Sequence> {
114 self.uri_collections.get(uri)
115 }
116
117 pub fn environment_variable(&self, name: &str) -> Option<&str> {
119 self.environment_variables.get(name).map(String::as_str)
120 }
121
122 pub fn environment_variable_names(&self) -> impl Iterator<Item = &str> {
124 self.environment_variables.keys().map(String::as_str)
125 }
126
127 pub(crate) fn arguments(&self) -> Result<Vec<sequence::Sequence>, Error> {
128 let mut arguments = Vec::new();
129 for variable_name in self.static_context().variable_names() {
130 let items = self.variables.get(variable_name).ok_or(Error::XPDY0002)?;
131 arguments.push(items.clone());
132 }
133 Ok(arguments)
134 }
135
136 fn create_current_datetime() -> chrono::DateTime<chrono::offset::FixedOffset> {
137 chrono::offset::Local::now().into()
138 }
139
140 pub(crate) fn current_datetime(&self) -> chrono::DateTime<chrono::offset::FixedOffset> {
141 self.current_datetime
142 }
143
144 pub fn implicit_timezone(&self) -> chrono::FixedOffset {
145 self.current_datetime.timezone()
146 }
147
148 pub fn function_info<'b>(&self, function: &'b Function) -> interpreter::FunctionInfo<'a, 'b> {
150 self.program.function_info(function)
151 }
152
153 pub(crate) fn static_function_by_id(
154 &self,
155 id: function::StaticFunctionId,
156 ) -> &function::StaticFunction {
157 self.program.static_context().function_by_id(id)
158 }
159
160 pub(crate) fn inline_function_by_id(
161 &self,
162 id: function::InlineFunctionId,
163 ) -> &function::InlineFunction {
164 self.program.inline_function(id)
165 }
166}