Skip to main content

opcua_nodes/
variable_type.rs

1// OPCUA for Rust
2// SPDX-License-Identifier: MPL-2.0
3// Copyright (C) 2017-2024 Adam Lock
4
5//! Contains the implementation of `VariableType` and `VariableTypeBuilder`.
6
7use opcua_types::{
8    AttributeId, AttributesMask, DataEncoding, DataValue, NumericRange, StatusCode,
9    TimestampsToReturn, TryFromVariant, VariableTypeAttributes, Variant,
10};
11use tracing::error;
12
13use crate::FromAttributesError;
14
15use super::{base::Base, node::Node, node::NodeBase};
16
17node_builder_impl!(VariableTypeBuilder, VariableType);
18
19node_builder_impl_generates_event!(VariableTypeBuilder);
20node_builder_impl_subtype!(VariableTypeBuilder);
21
22impl VariableTypeBuilder {
23    /// Set whether the variable type is abstract, meaning
24    /// it cannot be used by nodes in the instance hierarchy.
25    pub fn is_abstract(mut self, is_abstract: bool) -> Self {
26        self.node.set_is_abstract(is_abstract);
27        self
28    }
29
30    /// Set the variable type write mask.
31    pub fn write_mask(mut self, write_mask: WriteMask) -> Self {
32        self.node.set_write_mask(write_mask);
33        self
34    }
35
36    /// Set the base data type for instances of this type.
37    pub fn data_type(mut self, data_type: impl Into<NodeId>) -> Self {
38        self.node.set_data_type(data_type);
39        self
40    }
41
42    /// Set the default value for instances of this type.
43    pub fn value(mut self, value: impl Into<Variant>) -> Self {
44        self.node.set_value(value);
45        self
46    }
47
48    /// Set the array dimensions of this type.
49    pub fn array_dimensions(mut self, array_dimensions: &[u32]) -> Self {
50        self.node.set_array_dimensions(array_dimensions);
51        self
52    }
53
54    /// Set the value rank of this type.
55    pub fn value_rank(mut self, value_rank: i32) -> Self {
56        self.node.set_value_rank(value_rank);
57        self
58    }
59}
60
61/// A `VariableType` is a type of node within the `AddressSpace`.
62#[derive(Debug)]
63pub struct VariableType {
64    pub(super) base: Base,
65    pub(super) data_type: NodeId,
66    pub(super) is_abstract: bool,
67    pub(super) value_rank: i32,
68    pub(super) value: Option<DataValue>,
69    pub(super) array_dimensions: Option<Vec<u32>>,
70}
71
72impl Default for VariableType {
73    fn default() -> Self {
74        Self {
75            base: Base::new(NodeClass::VariableType, &NodeId::null(), "", ""),
76            data_type: NodeId::null(),
77            is_abstract: false,
78            value_rank: -1,
79            value: None,
80            array_dimensions: None,
81        }
82    }
83}
84
85node_base_impl!(VariableType);
86
87impl Node for VariableType {
88    fn get_attribute_max_age(
89        &self,
90        timestamps_to_return: TimestampsToReturn,
91        attribute_id: AttributeId,
92        index_range: &NumericRange,
93        data_encoding: &DataEncoding,
94        max_age: f64,
95    ) -> Option<DataValue> {
96        match attribute_id {
97            AttributeId::Value => self.value().cloned(),
98            AttributeId::DataType => Some(self.data_type().clone().into()),
99            AttributeId::IsAbstract => Some(self.is_abstract().into()),
100            AttributeId::ValueRank => Some(self.value_rank().into()),
101            // Optional attributes
102            AttributeId::ArrayDimensions => self.array_dimensions().map(DataValue::value_only),
103            _ => self.base.get_attribute_max_age(
104                timestamps_to_return,
105                attribute_id,
106                index_range,
107                data_encoding,
108                max_age,
109            ),
110        }
111    }
112
113    fn set_attribute(
114        &mut self,
115        attribute_id: AttributeId,
116        value: Variant,
117    ) -> Result<(), StatusCode> {
118        match attribute_id {
119            AttributeId::DataType => {
120                if let Variant::NodeId(v) = value {
121                    self.set_data_type(*v);
122                    Ok(())
123                } else {
124                    Err(StatusCode::BadTypeMismatch)
125                }
126            }
127            AttributeId::IsAbstract => {
128                if let Variant::Boolean(v) = value {
129                    self.set_is_abstract(v);
130                    Ok(())
131                } else {
132                    Err(StatusCode::BadTypeMismatch)
133                }
134            }
135            AttributeId::ValueRank => {
136                if let Variant::Int32(v) = value {
137                    self.set_value_rank(v);
138                    Ok(())
139                } else {
140                    Err(StatusCode::BadTypeMismatch)
141                }
142            }
143            AttributeId::Value => {
144                self.set_value(value);
145                Ok(())
146            }
147            AttributeId::ArrayDimensions => {
148                let array_dimensions = <Vec<u32>>::try_from_variant(value);
149                if let Ok(array_dimensions) = array_dimensions {
150                    self.set_array_dimensions(&array_dimensions);
151                    Ok(())
152                } else {
153                    Err(StatusCode::BadTypeMismatch)
154                }
155            }
156            _ => self.base.set_attribute(attribute_id, value),
157        }
158    }
159}
160
161impl VariableType {
162    /// Create a new variable type node.
163    pub fn new(
164        node_id: &NodeId,
165        browse_name: impl Into<QualifiedName>,
166        display_name: impl Into<LocalizedText>,
167        data_type: NodeId,
168        is_abstract: bool,
169        value_rank: i32,
170    ) -> VariableType {
171        VariableType {
172            base: Base::new(NodeClass::VariableType, node_id, browse_name, display_name),
173            data_type,
174            is_abstract,
175            value_rank,
176            value: None,
177            array_dimensions: None,
178        }
179    }
180
181    /// Create a new variable type with all attributes, may change if
182    /// new attributes are added to the OPC-UA standard.
183    pub fn new_full(
184        base: Base,
185        data_type: NodeId,
186        is_abstract: bool,
187        value_rank: i32,
188        value: Option<DataValue>,
189        array_dimensions: Option<Vec<u32>>,
190    ) -> Self {
191        Self {
192            base,
193            data_type,
194            is_abstract,
195            value,
196            value_rank,
197            array_dimensions,
198        }
199    }
200
201    /// Create a new variable type from [VariableTypeAttributes].
202    pub fn from_attributes(
203        node_id: &NodeId,
204        browse_name: impl Into<QualifiedName>,
205        attributes: VariableTypeAttributes,
206    ) -> Result<Self, FromAttributesError> {
207        let mandatory_attributes = AttributesMask::DISPLAY_NAME
208            | AttributesMask::IS_ABSTRACT
209            | AttributesMask::DATA_TYPE
210            | AttributesMask::VALUE_RANK;
211        let mask = AttributesMask::from_bits(attributes.specified_attributes)
212            .ok_or(FromAttributesError::InvalidMask)?;
213        if mask.contains(mandatory_attributes) {
214            let mut node = Self::new(
215                node_id,
216                browse_name,
217                attributes.display_name,
218                attributes.data_type,
219                attributes.is_abstract,
220                attributes.value_rank,
221            );
222            if mask.contains(AttributesMask::DESCRIPTION) {
223                node.set_description(attributes.description);
224            }
225            if mask.contains(AttributesMask::WRITE_MASK) {
226                node.set_write_mask(WriteMask::from_bits_truncate(attributes.write_mask));
227            }
228            if mask.contains(AttributesMask::USER_WRITE_MASK) {
229                node.set_user_write_mask(WriteMask::from_bits_truncate(attributes.user_write_mask));
230            }
231            if mask.contains(AttributesMask::VALUE) {
232                node.set_value(attributes.value);
233            }
234            if mask.contains(AttributesMask::ARRAY_DIMENSIONS) {
235                node.set_array_dimensions(attributes.array_dimensions.unwrap().as_slice());
236            }
237            Ok(node)
238        } else {
239            error!("VariableType cannot be created from attributes - missing mandatory values");
240            Err(FromAttributesError::MissingMandatoryValues)
241        }
242    }
243
244    /// Get whether this type is valid.
245    pub fn is_valid(&self) -> bool {
246        self.base.is_valid()
247    }
248
249    /// Get the data type of this variable type.
250    pub fn data_type(&self) -> &NodeId {
251        &self.data_type
252    }
253
254    /// Set the data type of this variable type.
255    pub fn set_data_type(&mut self, data_type: impl Into<NodeId>) {
256        self.data_type = data_type.into();
257    }
258
259    /// Get the `IsAbstract` attribute for this variable type.
260    pub fn is_abstract(&self) -> bool {
261        self.is_abstract
262    }
263
264    /// Set the `IsAbstract` attribute for this variable type.
265    pub fn set_is_abstract(&mut self, is_abstract: bool) {
266        self.is_abstract = is_abstract;
267    }
268
269    /// Get the value rank of this variable type.
270    pub fn value_rank(&self) -> i32 {
271        self.value_rank
272    }
273
274    /// Set the value rank of this variable type.
275    pub fn set_value_rank(&mut self, value_rank: i32) {
276        self.value_rank = value_rank;
277    }
278
279    /// Get the array dimensions of this type.
280    pub fn array_dimensions(&self) -> Option<Vec<u32>> {
281        self.array_dimensions.clone()
282    }
283
284    /// Set the array dimensions of this type.
285    pub fn set_array_dimensions(&mut self, array_dimensions: &[u32]) {
286        self.array_dimensions = Some(array_dimensions.to_vec());
287    }
288
289    /// Get the default value for instances of this type.
290    pub fn value(&self) -> Option<&DataValue> {
291        self.value.as_ref()
292    }
293
294    /// Set the default value for instances of this type.
295    pub fn set_value(&mut self, value: impl Into<Variant>) {
296        self.value = Some(DataValue::new_now(value));
297    }
298
299    /// Set the default value for instances of this type to
300    /// a full data value.
301    pub fn set_data_value(&mut self, value: DataValue) {
302        self.value = Some(value);
303    }
304}