1use opcua_types::{
8 AttributeId, AttributesMask, DataEncoding, DataTypeAttributes, DataTypeDefinition, DataValue,
9 NumericRange, StatusCode, TimestampsToReturn, Variant,
10};
11use tracing::error;
12
13use crate::FromAttributesError;
14
15use super::{base::Base, node::Node, node::NodeBase};
16
17node_builder_impl!(DataTypeBuilder, DataType);
18node_builder_impl_subtype!(DataTypeBuilder);
19
20impl DataTypeBuilder {
21 pub fn is_abstract(mut self, is_abstract: bool) -> Self {
24 self.node.set_is_abstract(is_abstract);
25 self
26 }
27
28 pub fn write_mask(mut self, write_mask: WriteMask) -> Self {
30 self.node.set_write_mask(write_mask);
31 self
32 }
33
34 pub fn data_type_definition(mut self, data_type_definition: DataTypeDefinition) -> Self {
36 self.node
37 .set_data_type_definition(Some(data_type_definition));
38 self
39 }
40}
41
42#[derive(Debug)]
44pub struct DataType {
45 pub(super) base: Base,
46 pub(super) is_abstract: bool,
47 pub(super) data_type_definition: Option<DataTypeDefinition>,
48}
49
50impl Default for DataType {
51 fn default() -> Self {
52 Self {
53 base: Base::new(NodeClass::DataType, &NodeId::null(), "", ""),
54 is_abstract: false,
55 data_type_definition: None,
56 }
57 }
58}
59
60node_base_impl!(DataType);
61
62impl Node for DataType {
63 fn get_attribute_max_age(
64 &self,
65 timestamps_to_return: TimestampsToReturn,
66 attribute_id: AttributeId,
67 index_range: &NumericRange,
68 data_encoding: &DataEncoding,
69 max_age: f64,
70 ) -> Option<DataValue> {
71 match attribute_id {
72 AttributeId::IsAbstract => Some(self.is_abstract().into()),
73 AttributeId::DataTypeDefinition => self.data_type_definition.as_ref().map(|dt| {
74 let v: Variant = dt.clone().into();
75 v.into()
76 }),
77 _ => self.base.get_attribute_max_age(
78 timestamps_to_return,
79 attribute_id,
80 index_range,
81 data_encoding,
82 max_age,
83 ),
84 }
85 }
86
87 fn set_attribute(
88 &mut self,
89 attribute_id: AttributeId,
90 value: Variant,
91 ) -> Result<(), StatusCode> {
92 match attribute_id {
93 AttributeId::IsAbstract => {
94 if let Variant::Boolean(v) = value {
95 self.set_is_abstract(v);
96 Ok(())
97 } else {
98 Err(StatusCode::BadTypeMismatch)
99 }
100 }
101 AttributeId::DataTypeDefinition => {
102 if matches!(value, Variant::Empty) {
103 self.set_data_type_definition(None);
104 Ok(())
105 } else if let Variant::ExtensionObject(v) = value {
106 let def = DataTypeDefinition::from_extension_object(v)?;
107 self.set_data_type_definition(Some(def));
108 Ok(())
109 } else {
110 Err(StatusCode::BadTypeMismatch)
111 }
112 }
113 _ => self.base.set_attribute(attribute_id, value),
114 }
115 }
116}
117
118impl DataType {
119 pub fn new(
121 node_id: &NodeId,
122 browse_name: impl Into<QualifiedName>,
123 display_name: impl Into<LocalizedText>,
124 is_abstract: bool,
125 ) -> DataType {
126 DataType {
127 base: Base::new(NodeClass::DataType, node_id, browse_name, display_name),
128 is_abstract,
129 data_type_definition: None,
130 }
131 }
132
133 pub fn new_full(
136 base: Base,
137 is_abstract: bool,
138 data_type_definition: Option<DataTypeDefinition>,
139 ) -> Self {
140 Self {
141 base,
142 is_abstract,
143 data_type_definition,
144 }
145 }
146
147 pub fn from_attributes(
149 node_id: &NodeId,
150 browse_name: impl Into<QualifiedName>,
151 attributes: DataTypeAttributes,
152 ) -> Result<Self, FromAttributesError> {
153 let mask = AttributesMask::from_bits(attributes.specified_attributes)
154 .ok_or(FromAttributesError::InvalidMask)?;
155 if mask.contains(AttributesMask::DISPLAY_NAME | AttributesMask::IS_ABSTRACT) {
156 let mut node = Self::new(
157 node_id,
158 browse_name,
159 attributes.display_name,
160 attributes.is_abstract,
161 );
162 if mask.contains(AttributesMask::DESCRIPTION) {
163 node.set_description(attributes.description);
164 }
165 if mask.contains(AttributesMask::WRITE_MASK) {
166 node.set_write_mask(WriteMask::from_bits_truncate(attributes.write_mask));
167 }
168 if mask.contains(AttributesMask::USER_WRITE_MASK) {
169 node.set_user_write_mask(WriteMask::from_bits_truncate(attributes.user_write_mask));
170 }
171 Ok(node)
172 } else {
173 error!("DataType cannot be created from attributes - missing mandatory values");
174 Err(FromAttributesError::MissingMandatoryValues)
175 }
176 }
177
178 pub fn is_valid(&self) -> bool {
180 self.base.is_valid()
181 }
182
183 pub fn is_abstract(&self) -> bool {
185 self.is_abstract
186 }
187
188 pub fn set_is_abstract(&mut self, is_abstract: bool) {
190 self.is_abstract = is_abstract;
191 }
192
193 pub fn set_data_type_definition(&mut self, data_type_definition: Option<DataTypeDefinition>) {
195 self.data_type_definition = data_type_definition;
196 }
197
198 pub fn data_type_definition(&self) -> Option<&DataTypeDefinition> {
200 self.data_type_definition.as_ref()
201 }
202}