1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
use opcua_types::{NodeId, QualifiedName, LocalizedText, AttributeId, DataValue, WriteMask};
use opcua_types::service_types::NodeClass;
use opcua_types::status_code::StatusCode;

use crate::address_space::types::{Object, ObjectType, ReferenceType, Variable, VariableType, View, DataType, Method};

#[derive(Debug)]
pub enum NodeType {
    Object(Object),
    ObjectType(ObjectType),
    ReferenceType(ReferenceType),
    Variable(Variable),
    VariableType(VariableType),
    View(View),
    DataType(DataType),
    Method(Method),
}

pub trait HasNodeId {
    fn node_id(&self) -> NodeId;
}

impl HasNodeId for NodeType {
    fn node_id(&self) -> NodeId {
        self.as_node().node_id()
    }
}

impl NodeType {
    pub fn as_node(&self) -> &dyn Node {
        match *self {
            NodeType::Object(ref value) => value,
            NodeType::ObjectType(ref value) => value,
            NodeType::ReferenceType(ref value) => value,
            NodeType::Variable(ref value) => value,
            NodeType::VariableType(ref value) => value,
            NodeType::View(ref value) => value,
            NodeType::DataType(ref value) => value,
            NodeType::Method(ref value) => value,
        }
    }

    pub fn as_mut_node(&mut self) -> &mut dyn Node {
        match *self {
            NodeType::Object(ref mut value) => value,
            NodeType::ObjectType(ref mut value) => value,
            NodeType::ReferenceType(ref mut value) => value,
            NodeType::Variable(ref mut value) => value,
            NodeType::VariableType(ref mut value) => value,
            NodeType::View(ref mut value) => value,
            NodeType::DataType(ref mut value) => value,
            NodeType::Method(ref mut value) => value,
        }
    }
}

/// Implemented by Base and all derived Node types. Functions that return a result in an Option
/// do so because the attribute is optional and not necessarily there.
pub trait Node {
    fn node_class(&self) -> NodeClass;
    fn node_id(&self) -> NodeId;
    fn browse_name(&self) -> QualifiedName;
    fn display_name(&self) -> LocalizedText;
    fn description(&self) -> Option<LocalizedText>;
    fn write_mask(&self) -> Option<WriteMask>;
    fn set_write_mask(&mut self, write_mask: WriteMask);
    fn user_write_mask(&self) -> Option<WriteMask>;
    fn set_user_write_mask(&mut self, write_mask: WriteMask);
    fn find_attribute(&self, attribute_id: AttributeId) -> Option<DataValue>;
    fn set_attribute(&mut self, attribute_id: AttributeId, value: DataValue) -> Result<(), StatusCode>;
}