1mod fallback;
10
11pub use fallback::{ByteStringBody, FallbackTypeLoader, JsonBody, XmlBody};
12
13use std::{borrow::Cow, io::Read, sync::Arc};
14
15use chrono::TimeDelta;
16use hashbrown::HashMap;
17
18use crate::{
19 BinaryDecodable, DecodingOptions, DynEncodable, EncodingResult, Error, GeneratedTypeLoader,
20 NamespaceMap, NodeId, UninitializedIndex,
21};
22
23type BinaryLoadFun = fn(&mut dyn Read, &Context<'_>) -> EncodingResult<Box<dyn DynEncodable>>;
24
25#[cfg(feature = "xml")]
26type XmlLoadFun = fn(
27 &mut crate::xml::XmlStreamReader<&mut dyn std::io::Read>,
28 &Context<'_>,
29) -> EncodingResult<Box<dyn DynEncodable>>;
30
31#[cfg(feature = "json")]
32type JsonLoadFun = fn(
33 &mut crate::json::JsonStreamReader<&mut dyn std::io::Read>,
34 &Context<'_>,
35) -> EncodingResult<Box<dyn DynEncodable>>;
36
37#[derive(Default)]
38pub struct TypeLoaderInstance {
40 binary_types: HashMap<u32, BinaryLoadFun>,
41
42 #[cfg(feature = "xml")]
43 xml_types: HashMap<u32, XmlLoadFun>,
44
45 #[cfg(feature = "json")]
46 json_types: HashMap<u32, JsonLoadFun>,
47}
48
49pub fn binary_decode_to_enc<T: DynEncodable + BinaryDecodable>(
51 stream: &mut dyn Read,
52 ctx: &Context<'_>,
53) -> EncodingResult<Box<dyn DynEncodable>> {
54 Ok(Box::new(T::decode(stream, ctx)?))
55}
56
57#[cfg(feature = "json")]
58pub fn json_decode_to_enc<T: DynEncodable + crate::json::JsonDecodable>(
60 stream: &mut crate::json::JsonStreamReader<&mut dyn std::io::Read>,
61 ctx: &Context<'_>,
62) -> EncodingResult<Box<dyn DynEncodable>> {
63 Ok(Box::new(T::decode(stream, ctx)?))
64}
65
66#[cfg(feature = "xml")]
67pub fn xml_decode_to_enc<T: DynEncodable + crate::xml::XmlDecodable>(
69 stream: &mut crate::xml::XmlStreamReader<&mut dyn std::io::Read>,
70 ctx: &Context<'_>,
71) -> EncodingResult<Box<dyn DynEncodable>> {
72 Ok(Box::new(T::decode(stream, ctx)?))
73}
74
75impl TypeLoaderInstance {
76 pub fn new() -> Self {
78 Self::default()
79 }
80
81 pub fn add_binary_type(&mut self, data_type: u32, encoding_type: u32, fun: BinaryLoadFun) {
83 self.binary_types.insert(data_type, fun);
84 self.binary_types.insert(encoding_type, fun);
85 }
86
87 #[cfg(feature = "xml")]
88 pub fn add_xml_type(&mut self, data_type: u32, encoding_type: u32, fun: XmlLoadFun) {
90 self.xml_types.insert(data_type, fun);
91 self.xml_types.insert(encoding_type, fun);
92 }
93
94 #[cfg(feature = "json")]
95 pub fn add_json_type(&mut self, data_type: u32, encoding_type: u32, fun: JsonLoadFun) {
97 self.json_types.insert(data_type, fun);
98 self.json_types.insert(encoding_type, fun);
99 }
100
101 pub fn decode_binary(
103 &self,
104 ty: u32,
105 stream: &mut dyn Read,
106 context: &Context<'_>,
107 ) -> Option<EncodingResult<Box<dyn DynEncodable>>> {
108 let fun = self.binary_types.get(&ty)?;
109 Some(fun(stream, context))
110 }
111
112 #[cfg(feature = "xml")]
113 pub fn decode_xml(
115 &self,
116 ty: u32,
117 stream: &mut crate::xml::XmlStreamReader<&mut dyn std::io::Read>,
118 context: &Context<'_>,
119 ) -> Option<EncodingResult<Box<dyn DynEncodable>>> {
120 let fun = self.xml_types.get(&ty)?;
121 Some(fun(stream, context))
122 }
123
124 #[cfg(feature = "json")]
125 pub fn decode_json(
127 &self,
128 ty: u32,
129 stream: &mut crate::json::JsonStreamReader<&mut dyn std::io::Read>,
130 context: &Context<'_>,
131 ) -> Option<EncodingResult<Box<dyn DynEncodable>>> {
132 let fun = self.json_types.get(&ty)?;
133 Some(fun(stream, context))
134 }
135}
136
137pub trait StaticTypeLoader {
142 fn instance() -> &'static TypeLoaderInstance;
144
145 fn namespace() -> &'static str;
147}
148
149impl<T> TypeLoader for T
150where
151 T: StaticTypeLoader + Send + Sync + 'static,
152{
153 #[cfg(feature = "xml")]
154 fn load_from_xml(
155 &self,
156 node_id: &crate::NodeId,
157 stream: &mut crate::xml::XmlStreamReader<&mut dyn std::io::Read>,
158 ctx: &Context<'_>,
159 _name: &str,
160 ) -> Option<crate::EncodingResult<Box<dyn crate::DynEncodable>>> {
161 let idx = ctx.namespaces().get_index(Self::namespace())?;
162 if idx != node_id.namespace {
163 return None;
164 }
165 let Some(num_id) = node_id.as_u32() else {
166 return Some(Err(Error::decoding(
167 "Unsupported encoding ID. Only numeric encoding IDs are currently supported",
168 )));
169 };
170 Self::instance().decode_xml(num_id, stream, ctx)
171 }
172
173 #[cfg(feature = "json")]
174 fn load_from_json(
175 &self,
176 node_id: &crate::NodeId,
177 stream: &mut crate::json::JsonStreamReader<&mut dyn std::io::Read>,
178 ctx: &Context<'_>,
179 ) -> Option<crate::EncodingResult<Box<dyn crate::DynEncodable>>> {
180 let idx = ctx.namespaces().get_index(Self::namespace())?;
181 if idx != node_id.namespace {
182 return None;
183 }
184 let Some(num_id) = node_id.as_u32() else {
185 return Some(Err(Error::decoding(
186 "Unsupported encoding ID. Only numeric encoding IDs are currently supported",
187 )));
188 };
189 Self::instance().decode_json(num_id, stream, ctx)
190 }
191
192 fn load_from_binary(
193 &self,
194 node_id: &NodeId,
195 stream: &mut dyn Read,
196 ctx: &Context<'_>,
197 _length: Option<usize>,
198 ) -> Option<crate::EncodingResult<Box<dyn crate::DynEncodable>>> {
199 let idx = ctx.namespaces().get_index(Self::namespace())?;
200 if idx != node_id.namespace {
201 return None;
202 }
203 let Some(num_id) = node_id.as_u32() else {
204 return Some(Err(Error::decoding(
205 "Unsupported encoding ID. Only numeric encoding IDs are currently supported",
206 )));
207 };
208 Self::instance().decode_binary(num_id, stream, ctx)
209 }
210
211 fn priority(&self) -> TypeLoaderPriority {
212 TypeLoaderPriority::Generated
213 }
214}
215
216pub struct ContextOwned {
220 namespaces: NamespaceMap,
221 loaders: TypeLoaderCollection,
222 options: DecodingOptions,
223}
224
225impl std::fmt::Debug for ContextOwned {
226 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
227 f.debug_struct("ContextOwned")
228 .field("namespaces", &self.namespaces)
229 .field("options", &self.options)
230 .finish()
231 }
232}
233
234impl ContextOwned {
235 pub fn new(
237 namespaces: NamespaceMap,
238 loaders: TypeLoaderCollection,
239 options: DecodingOptions,
240 ) -> Self {
241 Self {
242 namespaces,
243 loaders,
244 options,
245 }
246 }
247
248 pub fn new_default(namespaces: NamespaceMap, options: DecodingOptions) -> Self {
250 Self::new(namespaces, TypeLoaderCollection::new(), options)
251 }
252
253 pub fn context(&self) -> Context<'_> {
255 Context {
256 namespaces: &self.namespaces,
257 loaders: &self.loaders,
258 options: self.options.clone(),
259 aliases: None,
260 index_map: None,
261 }
262 }
263
264 pub fn namespaces(&self) -> &NamespaceMap {
266 &self.namespaces
267 }
268
269 pub fn namespaces_mut(&mut self) -> &mut NamespaceMap {
271 &mut self.namespaces
272 }
273
274 pub fn options(&self) -> &DecodingOptions {
276 &self.options
277 }
278
279 pub fn options_mut(&mut self) -> &mut DecodingOptions {
281 &mut self.options
282 }
283
284 pub fn loaders_mut(&mut self) -> &mut TypeLoaderCollection {
286 &mut self.loaders
287 }
288}
289
290impl Default for ContextOwned {
291 fn default() -> Self {
292 Self::new_default(Default::default(), Default::default())
293 }
294}
295
296#[derive(Clone)]
297pub struct TypeLoaderCollection {
300 loaders: Vec<Arc<dyn TypeLoader>>,
301}
302
303impl Default for TypeLoaderCollection {
304 fn default() -> Self {
305 Self::new()
306 }
307}
308
309impl TypeLoaderCollection {
310 pub fn new() -> Self {
313 Self {
314 loaders: vec![Arc::new(GeneratedTypeLoader), Arc::new(FallbackTypeLoader)],
315 }
316 }
317
318 pub fn new_empty() -> Self {
321 Self {
322 loaders: Vec::new(),
323 }
324 }
325
326 pub fn add_type_loader(&mut self, loader: impl TypeLoader + 'static) {
328 self.add(Arc::new(loader));
329 }
330
331 pub fn add(&mut self, loader: Arc<dyn TypeLoader>) {
333 let priority = loader.priority();
334 for i in 0..self.loaders.len() {
335 if self.loaders[i].priority() > priority {
336 self.loaders.insert(i, loader);
337 return;
338 }
339 }
340 self.loaders.push(loader);
341 }
342
343 pub fn iter(&self) -> <&Self as IntoIterator>::IntoIter {
345 self.into_iter()
346 }
347}
348
349impl<'a> IntoIterator for &'a TypeLoaderCollection {
350 type Item = &'a Arc<dyn TypeLoader>;
351
352 type IntoIter = <&'a [Arc<dyn TypeLoader>] as IntoIterator>::IntoIter;
353
354 fn into_iter(self) -> Self::IntoIter {
355 self.loaders.iter()
356 }
357}
358
359#[derive(Clone)]
360pub struct Context<'a> {
362 namespaces: &'a NamespaceMap,
363 loaders: &'a TypeLoaderCollection,
364 options: DecodingOptions,
365 aliases: Option<&'a HashMap<String, String>>,
366 index_map: Option<&'a HashMap<u16, u16>>,
367}
368
369#[derive(Debug, Copy, Clone, PartialEq, Eq)]
370pub enum TypeLoaderPriority {
375 Core,
377 Generated,
379 Dynamic(u32),
382 Fallback,
384}
385
386impl TypeLoaderPriority {
387 pub fn priority(&self) -> u32 {
389 match self {
390 Self::Core => 0,
391 Self::Generated => 1,
392 Self::Dynamic(v) => *v,
393 Self::Fallback => u32::MAX,
394 }
395 }
396}
397
398impl PartialOrd for TypeLoaderPriority {
399 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
400 Some(self.cmp(other))
401 }
402}
403
404impl Ord for TypeLoaderPriority {
405 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
406 self.priority().cmp(&other.priority())
407 }
408}
409
410pub trait TypeLoader: Send + Sync {
416 #[cfg(feature = "xml")]
417 fn load_from_xml(
420 &self,
421 node_id: &crate::NodeId,
422 stream: &mut crate::xml::XmlStreamReader<&mut dyn std::io::Read>,
423 ctx: &Context<'_>,
424 name: &str,
425 ) -> Option<crate::EncodingResult<Box<dyn crate::DynEncodable>>>;
426
427 #[cfg(feature = "json")]
428 fn load_from_json(
431 &self,
432 node_id: &crate::NodeId,
433 stream: &mut crate::json::JsonStreamReader<&mut dyn std::io::Read>,
434 ctx: &Context<'_>,
435 ) -> Option<crate::EncodingResult<Box<dyn crate::DynEncodable>>>;
436
437 fn load_from_binary(
440 &self,
441 node_id: &NodeId,
442 stream: &mut dyn Read,
443 ctx: &Context<'_>,
444 length: Option<usize>,
445 ) -> Option<crate::EncodingResult<Box<dyn crate::DynEncodable>>>;
446
447 fn priority(&self) -> TypeLoaderPriority {
449 TypeLoaderPriority::Generated
450 }
451}
452
453impl<'a> Context<'a> {
454 pub fn new(
457 namespaces: &'a NamespaceMap,
458 loaders: &'a TypeLoaderCollection,
459 options: DecodingOptions,
460 ) -> Self {
461 Self {
462 namespaces,
463 loaders,
464 options,
465 aliases: None,
466 index_map: None,
467 }
468 }
469
470 #[cfg(feature = "json")]
471 pub fn load_from_json(
474 &self,
475 node_id: &NodeId,
476 stream: &mut crate::json::JsonStreamReader<&mut dyn Read>,
477 ) -> crate::EncodingResult<crate::ExtensionObject> {
478 for loader in self.loaders {
479 if let Some(r) = loader.load_from_json(node_id, stream, self) {
480 return Ok(crate::ExtensionObject { body: Some(r?) });
481 }
482 }
483 Err(Error::decoding(format!(
484 "No type loader defined for {node_id}"
485 )))
486 }
487
488 pub fn load_from_binary(
491 &self,
492 node_id: &NodeId,
493 stream: &mut dyn Read,
494 length: Option<usize>,
495 ) -> crate::EncodingResult<crate::ExtensionObject> {
496 for loader in self.loaders {
497 if let Some(r) = loader.load_from_binary(node_id, stream, self, length) {
498 return Ok(crate::ExtensionObject { body: Some(r?) });
499 }
500 }
501 Err(Error::decoding(format!(
502 "No type loader defined for {node_id}"
503 )))
504 }
505
506 #[cfg(feature = "xml")]
507 pub fn load_from_xml(
510 &self,
511 node_id: &NodeId,
512 stream: &mut crate::xml::XmlStreamReader<&mut dyn std::io::Read>,
513 name: &str,
514 ) -> crate::EncodingResult<crate::ExtensionObject> {
515 for loader in self.loaders {
516 if let Some(r) = loader.load_from_xml(node_id, stream, self, name) {
517 return Ok(crate::ExtensionObject { body: Some(r?) });
518 }
519 }
520 Err(Error::decoding(format!(
521 "No type loader defined for {node_id}"
522 )))
523 }
524
525 pub fn options(&self) -> &DecodingOptions {
527 &self.options
528 }
529
530 pub fn namespaces(&self) -> &'a NamespaceMap {
532 self.namespaces
533 }
534
535 pub fn set_index_map(&mut self, index_map: &'a HashMap<u16, u16>) {
537 self.index_map = Some(index_map);
538 }
539
540 pub fn set_aliases(&mut self, aliases: &'a HashMap<String, String>) {
542 self.aliases = Some(aliases);
543 }
544
545 pub fn resolve_namespace_index(
548 &self,
549 index_in_node_set: u16,
550 ) -> Result<u16, UninitializedIndex> {
551 if index_in_node_set == 0 {
552 return Ok(0);
553 }
554
555 let Some(index_map) = self.index_map else {
556 return Ok(index_in_node_set);
557 };
558 let Some(idx) = index_map.get(&index_in_node_set) else {
559 return Err(UninitializedIndex(index_in_node_set));
560 };
561 Ok(*idx)
562 }
563
564 pub fn resolve_namespace_index_inverse(
567 &self,
568 index_in_server: u16,
569 ) -> Result<u16, UninitializedIndex> {
570 if index_in_server == 0 {
571 return Ok(0);
572 }
573
574 let Some(index_map) = self.index_map else {
575 return Ok(index_in_server);
576 };
577 let Some((idx, _)) = index_map.iter().find(|(_, &v)| v == index_in_server) else {
578 return Err(UninitializedIndex(index_in_server));
579 };
580 Ok(*idx)
581 }
582
583 pub fn resolve_alias<'b>(&self, node_id_str: &'b str) -> &'b str
586 where
587 'a: 'b,
588 {
589 if let Some(aliases) = self.aliases {
590 if let Some(alias) = aliases.get(node_id_str) {
591 return alias.as_str();
592 }
593 }
594 node_id_str
595 }
596
597 pub fn resolve_alias_inverse<'b>(&self, node_id_str: &'b str) -> &'b str
599 where
600 'a: 'b,
601 {
602 if let Some(aliases) = self.aliases {
603 for (k, v) in aliases.iter() {
604 if v == node_id_str {
605 return k.as_str();
606 }
607 }
608 }
609 node_id_str
610 }
611
612 pub fn with_zero_offset(&self) -> Cow<'_, Self> {
615 if self.options.client_offset.is_zero() {
616 Cow::Borrowed(self)
617 } else {
618 Cow::Owned(Self {
619 namespaces: self.namespaces,
620 loaders: self.loaders,
621 options: DecodingOptions {
622 client_offset: TimeDelta::zero(),
623 ..self.options.clone()
624 },
625 aliases: self.aliases,
626 index_map: self.index_map,
627 })
628 }
629 }
630}