opcua_types/
namespaces.rs1use hashbrown::HashMap;
4
5use crate::{errors::OpcUaError, ExpandedNodeId, NodeId, Variant};
6
7#[derive(Debug, Default, Clone)]
9pub struct NamespaceMap {
10 known_namespaces: HashMap<String, u16>,
11}
12
13impl NamespaceMap {
14 pub fn new() -> Self {
16 let mut known_namespaces = HashMap::new();
17 known_namespaces.insert("http://opcfoundation.org/UA/".to_owned(), 0u16);
18
19 Self { known_namespaces }
20 }
21
22 pub fn new_full(map: HashMap<String, u16>) -> Self {
24 Self {
25 known_namespaces: map,
26 }
27 }
28
29 pub fn new_from_variant_array(array: &[Variant]) -> Result<Self, OpcUaError> {
32 let known_namespaces: HashMap<String, u16> = array
33 .iter()
34 .enumerate()
35 .map(|(idx, v)| {
36 if let Variant::String(s) = v {
37 Ok((s.value().clone().unwrap_or(String::new()), idx as u16))
38 } else {
39 Err(OpcUaError::UnexpectedVariantType {
40 variant_id: v.scalar_type_id(),
41 message: "Namespace array on server contains invalid data".to_string(),
42 })
43 }
44 })
45 .collect::<Result<HashMap<_, _>, _>>()?;
46 Ok(Self { known_namespaces })
47 }
48
49 pub fn add_namespace(&mut self, namespace: &str) -> u16 {
52 if let Some(ns) = self.known_namespaces.get(namespace) {
53 return *ns;
54 }
55 let max = self
56 .known_namespaces
57 .iter()
58 .map(|kv| *kv.1)
59 .max()
60 .unwrap_or_default();
61 self.known_namespaces.insert(namespace.to_owned(), max + 1);
62
63 max + 1
64 }
65
66 pub fn known_namespaces(&self) -> &HashMap<String, u16> {
68 &self.known_namespaces
69 }
70
71 pub fn get_index(&self, ns: &str) -> Option<u16> {
73 self.known_namespaces.get(ns).copied()
74 }
75
76 pub fn resolve_node_id<'b>(
78 &self,
79 id: &'b ExpandedNodeId,
80 ) -> Option<std::borrow::Cow<'b, NodeId>> {
81 id.try_resolve(self)
82 }
83}
84
85pub struct NodeSetNamespaceMapper<'a> {
87 namespaces: &'a mut NamespaceMap,
88 index_map: HashMap<u16, u16>,
89}
90
91#[derive(Debug)]
92pub struct UninitializedIndex(pub u16);
94
95impl<'a> NodeSetNamespaceMapper<'a> {
96 pub fn new(namespaces: &'a mut NamespaceMap) -> Self {
98 Self {
99 namespaces,
100 index_map: HashMap::new(),
101 }
102 }
103
104 pub fn add_namespace(&mut self, namespace: &str, index_in_node_set: u16) {
106 let index = self.namespaces.add_namespace(namespace);
107 self.index_map.insert(index_in_node_set, index);
108 }
109
110 pub fn get_index(&self, index_in_node_set: u16) -> Result<u16, UninitializedIndex> {
112 if index_in_node_set == 0 {
113 return Ok(0);
114 }
115 let Some(idx) = self.index_map.get(&index_in_node_set) else {
116 return Err(UninitializedIndex(index_in_node_set));
117 };
118 Ok(*idx)
119 }
120
121 pub fn namespaces(&'a self) -> &'a NamespaceMap {
123 &*self.namespaces
124 }
125
126 pub fn index_map(&self) -> &HashMap<u16, u16> {
128 &self.index_map
129 }
130}