1use bitflags::bitflags;
7
8mod events;
9mod generic;
10mod import;
11mod references;
12mod type_tree;
13#[cfg(feature = "xml")]
14mod xml;
15#[cfg(feature = "xml")]
16pub use xml::NodeSet2Import;
17
18pub use base::Base;
19pub use data_type::{DataType, DataTypeBuilder};
20pub use events::*;
21pub use generic::new_node_from_attributes;
22pub use import::{ImportedItem, ImportedReference, NodeSetImport, NodeSetNamespaceMapper};
23pub use method::{Method, MethodBuilder};
24pub use node::{HasNodeId, Node, NodeBase, NodeType};
25pub use object::{Object, ObjectBuilder};
26pub use object_type::{ObjectType, ObjectTypeBuilder};
27pub use opcua_types::NamespaceMap;
28use opcua_types::NodeId;
29pub use reference_type::{ReferenceType, ReferenceTypeBuilder};
30pub use references::{Reference, ReferenceRef, References};
31pub use type_tree::{
32 DefaultTypeTree, TypeProperty, TypePropertyInverseRef, TypeTree, TypeTreeNode,
33};
34pub use variable::{Variable, VariableBuilder};
35pub use variable_type::{VariableType, VariableTypeBuilder};
36pub use view::{View, ViewBuilder};
37
38pub use opcua_macros::{Event, EventField};
39
40#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
41pub enum ReferenceDirection {
43 Forward,
45 Inverse,
47}
48
49#[derive(Debug)]
50pub enum FromAttributesError {
52 InvalidMask,
54 MissingMandatoryValues,
56}
57
58pub trait NodeInsertTarget {
61 fn insert<'a>(
63 &mut self,
64 node: impl Into<NodeType>,
65 references: Option<&'a [(&'a NodeId, &NodeId, ReferenceDirection)]>,
66 ) -> bool;
67}
68
69macro_rules! node_builder_impl {
72 ( $node_builder_ty:ident, $node_ty:ident ) => {
73 use opcua_types::{LocalizedText, NodeId, QualifiedName, ReferenceTypeId};
74 use tracing::trace;
75 use $crate::ReferenceDirection;
76 pub struct $node_builder_ty {
81 node: $node_ty,
82 references: Vec<(NodeId, NodeId, ReferenceDirection)>,
83 }
84
85 impl $node_builder_ty {
86 pub fn new<T, S>(node_id: &NodeId, browse_name: T, display_name: S) -> Self
88 where
89 T: Into<QualifiedName>,
90 S: Into<LocalizedText>,
91 {
92 trace!("Creating a node using a builder, node id {}", node_id);
93 Self {
94 node: $node_ty::default(),
95 references: Vec::with_capacity(10),
96 }
97 .node_id(node_id.clone())
98 .browse_name(browse_name)
99 .display_name(display_name)
100 }
101
102 pub fn get_node_id(&self) -> &NodeId {
104 self.node.node_id()
105 }
106
107 fn node_id(mut self, node_id: NodeId) -> Self {
108 let _ = self.node.base.set_node_id(node_id);
109 self
110 }
111
112 fn browse_name<V>(mut self, browse_name: V) -> Self
113 where
114 V: Into<QualifiedName>,
115 {
116 let _ = self.node.base.set_browse_name(browse_name);
117 self
118 }
119
120 fn display_name<V>(mut self, display_name: V) -> Self
121 where
122 V: Into<LocalizedText>,
123 {
124 self.node.set_display_name(display_name.into());
125 self
126 }
127
128 pub fn is_valid(&self) -> bool {
130 self.node.is_valid()
131 }
132
133 pub fn description<V>(mut self, description: V) -> Self
135 where
136 V: Into<LocalizedText>,
137 {
138 self.node.set_description(description.into());
139 self
140 }
141
142 pub fn reference<T>(
144 mut self,
145 node_id: T,
146 reference_type_id: ReferenceTypeId,
147 reference_direction: ReferenceDirection,
148 ) -> Self
149 where
150 T: Into<NodeId>,
151 {
152 self.references.push((
153 node_id.into(),
154 reference_type_id.into(),
155 reference_direction,
156 ));
157 self
158 }
159
160 pub fn organizes<T>(self, organizes_id: T) -> Self
162 where
163 T: Into<NodeId>,
164 {
165 self.reference(
166 organizes_id,
167 ReferenceTypeId::Organizes,
168 ReferenceDirection::Forward,
169 )
170 }
171
172 pub fn organized_by<T>(self, organized_by_id: T) -> Self
174 where
175 T: Into<NodeId>,
176 {
177 self.reference(
178 organized_by_id,
179 ReferenceTypeId::Organizes,
180 ReferenceDirection::Inverse,
181 )
182 }
183
184 pub fn build(self) -> $node_ty {
188 if self.is_valid() {
189 self.node
190 } else {
191 panic!(
192 "The node is not valid, node id = {:?}",
193 self.node.base.node_id()
194 );
195 }
196 }
197
198 pub fn insert(self, address_space: &mut impl crate::NodeInsertTarget) -> bool {
201 if self.is_valid() {
202 if !self.references.is_empty() {
203 let references = self
204 .references
205 .iter()
206 .map(|v| (&v.0, &v.1, v.2))
207 .collect::<Vec<_>>();
208 address_space.insert(self.node, Some(references.as_slice()))
209 } else {
210 address_space.insert(self.node, None)
211 }
212 } else {
213 panic!(
214 "The node is not valid, node id = {:?}",
215 self.node.base.node_id()
216 );
217 }
218 }
219 }
220 };
221}
222
223macro_rules! node_builder_impl_generates_event {
224 ( $node_builder_ty:ident ) => {
225 impl $node_builder_ty {
226 pub fn generates_event<T>(self, event_type: T) -> Self
228 where
229 T: Into<NodeId>,
230 {
231 self.reference(
232 event_type,
233 ReferenceTypeId::GeneratesEvent,
234 ReferenceDirection::Forward,
235 )
236 }
237 }
238 };
239}
240
241macro_rules! node_builder_impl_subtype {
242 ( $node_builder_ty:ident ) => {
243 impl $node_builder_ty {
244 pub fn subtype_of<T>(self, type_id: T) -> Self
247 where
248 T: Into<NodeId>,
249 {
250 self.reference(
251 type_id,
252 ReferenceTypeId::HasSubtype,
253 ReferenceDirection::Inverse,
254 )
255 }
256
257 pub fn has_subtype<T>(self, subtype_id: T) -> Self
259 where
260 T: Into<NodeId>,
261 {
262 self.reference(
263 subtype_id,
264 ReferenceTypeId::HasSubtype,
265 ReferenceDirection::Forward,
266 )
267 }
268 }
269 };
270}
271
272macro_rules! node_builder_impl_component_of {
273 ( $node_builder_ty:ident ) => {
274 impl $node_builder_ty {
275 pub fn component_of<T>(self, component_of_id: T) -> Self
278 where
279 T: Into<NodeId>,
280 {
281 self.reference(
282 component_of_id,
283 ReferenceTypeId::HasComponent,
284 ReferenceDirection::Inverse,
285 )
286 }
287 pub fn has_component<T>(self, has_component_id: T) -> Self
290 where
291 T: Into<NodeId>,
292 {
293 self.reference(
294 has_component_id,
295 ReferenceTypeId::HasComponent,
296 ReferenceDirection::Forward,
297 )
298 }
299 }
300 };
301}
302
303macro_rules! node_builder_impl_property_of {
304 ( $node_builder_ty:ident ) => {
305 impl $node_builder_ty {
306 pub fn has_property<T>(self, has_component_id: T) -> Self
308 where
309 T: Into<NodeId>,
310 {
311 self.reference(
312 has_component_id,
313 ReferenceTypeId::HasProperty,
314 ReferenceDirection::Forward,
315 )
316 }
317
318 pub fn property_of<T>(self, component_of_id: T) -> Self
320 where
321 T: Into<NodeId>,
322 {
323 self.reference(
324 component_of_id,
325 ReferenceTypeId::HasProperty,
326 ReferenceDirection::Inverse,
327 )
328 }
329 }
330 };
331}
332
333macro_rules! node_base_impl {
336 ( $node_struct:ident ) => {
337 use crate::NodeType;
338 use opcua_types::{NodeClass, WriteMask};
339
340 impl From<$node_struct> for NodeType {
341 fn from(value: $node_struct) -> Self {
342 Self::$node_struct(Box::new(value))
343 }
344 }
345
346 impl crate::NodeBase for $node_struct {
347 fn node_class(&self) -> NodeClass {
348 self.base.node_class()
349 }
350
351 fn node_id(&self) -> &NodeId {
352 self.base.node_id()
353 }
354
355 fn browse_name(&self) -> &QualifiedName {
356 self.base.browse_name()
357 }
358
359 fn display_name(&self) -> &LocalizedText {
360 self.base.display_name()
361 }
362
363 fn set_display_name(&mut self, display_name: LocalizedText) {
364 self.base.set_display_name(display_name);
365 }
366
367 fn description(&self) -> Option<&LocalizedText> {
368 self.base.description()
369 }
370
371 fn set_description(&mut self, description: LocalizedText) {
372 self.base.set_description(description);
373 }
374
375 fn write_mask(&self) -> Option<WriteMask> {
376 self.base.write_mask()
377 }
378
379 fn set_write_mask(&mut self, write_mask: WriteMask) {
380 self.base.set_write_mask(write_mask);
381 }
382
383 fn user_write_mask(&self) -> Option<WriteMask> {
384 self.base.user_write_mask()
385 }
386
387 fn set_user_write_mask(&mut self, user_write_mask: WriteMask) {
388 self.base.set_user_write_mask(user_write_mask)
389 }
390 }
391 };
392}
393
394mod base;
395mod data_type;
396mod method;
398mod node;
399mod object;
400mod object_type;
401mod reference_type;
402mod variable;
403mod variable_type;
404mod view;
405
406bitflags! {
407 #[derive(Debug, Clone, Copy, Default)]
408 pub struct AccessLevel: u8 {
410 const CURRENT_READ = 1;
412 const CURRENT_WRITE = 2;
414 const HISTORY_READ = 4;
416 const HISTORY_WRITE = 8;
418 const SEMANTIC_CHANGE = 16;
420 const STATUS_WRITE = 32;
422 const TIMESTAMP_WRITE = 64;
424 }
425}
426
427bitflags! {
428 #[derive(Debug, Clone, Copy, Default)]
429 pub struct EventNotifier: u8 {
431 const SUBSCRIBE_TO_EVENTS = 1;
433 const HISTORY_READ = 4;
435 const HISTORY_WRITE = 8;
437 }
438}