Skip to main content

open62541/ua/data_types/
variant.rs

1use std::ffi::c_void;
2
3use open62541_sys::{
4    UA_Variant_clear, UA_Variant_hasArrayType, UA_Variant_hasScalarType, UA_Variant_isEmpty,
5    UA_Variant_isScalar, UA_Variant_setArray, UA_Variant_setScalar, UA_Variant_setScalarCopy,
6};
7
8use crate::{DataType, NonScalarValue, ScalarValue, ValueType, VariantValue, ua};
9
10crate::data_type!(Variant);
11
12impl Variant {
13    /// Creates variant from scalar.
14    #[must_use]
15    pub fn scalar<T: DataType>(value: T) -> Self {
16        let mut variant = Self::init();
17        // This gives up ownership of the scalar, then moves it into the variant which becomes the
18        // new owner.
19        let ptr = value.leak_into_raw();
20        unsafe {
21            UA_Variant_setScalar(variant.as_mut_ptr(), ptr.cast::<c_void>(), T::data_type());
22        }
23        variant
24    }
25
26    /// Creates variant from array.
27    #[must_use]
28    pub fn array<T: DataType>(value: ua::Array<T>) -> Self {
29        let mut variant = Self::init();
30        // This gives up ownership of the array, then moves it into the variant which becomes the
31        // new owner.
32        let (size, ptr) = value.into_raw_parts();
33        unsafe {
34            UA_Variant_setArray(
35                variant.as_mut_ptr(),
36                ptr.cast::<c_void>(),
37                size,
38                T::data_type(),
39            );
40        }
41        variant
42    }
43
44    #[must_use]
45    pub fn with_scalar<T: DataType>(mut self, value: &T) -> Self {
46        // The call to `UA_Variant_setScalarCopy()` does not free held memory which would lead to a
47        // memory leak. We must clear the variant manually to handle the case where `with_scalar()`
48        // is called multiple times on the same `Variant`.
49        unsafe {
50            UA_Variant_clear(self.as_mut_ptr());
51            UA_Variant_setScalarCopy(
52                self.as_mut_ptr(),
53                value.as_ptr().cast::<c_void>(),
54                T::data_type(),
55            );
56        }
57        self
58    }
59
60    /// Gets data type's node ID.
61    ///
62    /// Returns `None` when the variant is empty.
63    #[must_use]
64    pub fn type_id(&self) -> Option<&ua::NodeId> {
65        let data_type = unsafe { self.0.type_.as_ref() };
66        data_type.map(|data_type| ua::NodeId::raw_ref(&data_type.typeId))
67    }
68
69    /// Gets value type.
70    ///
71    /// Returns `None` when the variant is empty.
72    #[must_use]
73    pub fn value_type(&self) -> Option<ValueType> {
74        self.type_id().map(ValueType::from_data_type)
75    }
76
77    #[must_use]
78    pub fn is_empty(&self) -> bool {
79        unsafe { UA_Variant_isEmpty(self.as_ptr()) }
80    }
81
82    #[must_use]
83    pub fn is_scalar(&self) -> bool {
84        unsafe { UA_Variant_isScalar(self.as_ptr()) }
85    }
86
87    #[must_use]
88    pub fn as_scalar<T>(&self) -> Option<&T>
89    where
90        T: DataType,
91    {
92        self.scalar_data::<T>()
93            // SAFETY: Inner pointer holds valid data.
94            .and_then(|data| unsafe { data.as_ref() })
95            .map(T::raw_ref)
96    }
97
98    #[must_use]
99    pub fn to_scalar<T>(&self) -> Option<T>
100    where
101        T: DataType,
102    {
103        self.scalar_data::<T>()
104            // SAFETY: Inner pointer holds valid data.
105            .and_then(|data| unsafe { data.as_ref() })
106            .map(T::clone_raw)
107    }
108
109    #[must_use]
110    pub fn into_scalar<T>(self) -> Option<T>
111    where
112        T: DataType,
113    {
114        self.scalar_data::<T>()
115            // SAFETY: Inner pointer holds valid data and we have exclusive access through `self`.
116            .and_then(|data| unsafe { data.cast_mut().as_mut() })
117            .map(T::take_raw)
118    }
119
120    #[must_use]
121    fn scalar_data<T: DataType>(&self) -> Option<*const T::Inner> {
122        if unsafe { UA_Variant_hasScalarType(self.as_ptr(), T::data_type()) } {
123            Some(self.0.data.cast::<T::Inner>())
124        } else {
125            if T::data_type() != Self::data_type() {
126                return None;
127            }
128            // If type conversion to `ua::Variant` is requested, we fall back to `self` as-is (OPC
129            // UA specifies that variants cannot directly contain other variants; we use this here
130            // to allow idempotent unwrapping which is useful in generic code).
131            Some(unsafe { self.as_ptr().cast::<T::Inner>() })
132        }
133    }
134
135    #[must_use]
136    pub fn to_array<T: DataType>(&self) -> Option<ua::Array<T>> {
137        if !unsafe { UA_Variant_hasArrayType(self.as_ptr(), T::data_type()) } {
138            // Special case: open62541 automatically converts arrays of extension objects into the
139            // contained data type (as of version 1.4). This only works for non-empty arrays since
140            // the element type needs to be known.
141            //
142            // To make handling such arrays easier in user code, we allow _coercion_ of such empty
143            // arrays into any data type.
144            let is_empty_structured_array = self.0.arrayLength == 0
145                && unsafe {
146                    UA_Variant_hasArrayType(self.as_ptr(), ua::ExtensionObject::data_type())
147                };
148            if !is_empty_structured_array {
149                return None;
150            }
151            // Fall through to let `ua::Array::from_raw_parts()` handle the distinction between an
152            // empty and an invalid array (where `self.0.data` is the sentinel value or null).
153        }
154        ua::Array::from_raw_parts(self.0.arrayLength, self.0.data.cast::<T::Inner>())
155    }
156
157    #[must_use]
158    pub fn to_value(&self) -> VariantValue {
159        if self.is_empty() {
160            return VariantValue::Empty;
161        }
162
163        if !self.is_scalar() {
164            // TODO: Handle non-scalar (array) values.
165            return VariantValue::NonScalar(NonScalarValue);
166        }
167
168        macro_rules! check {
169            ($( $name:ident($type:ty) ),* $(,)?) => {
170                $(
171                    if let Some(value) = self.to_scalar::<$type>() {
172                        return VariantValue::Scalar(ScalarValue::$name(value));
173                    }
174                )*
175            };
176        }
177
178        // This mirrors the definition of `ScalarValue`.
179        check!(
180            Boolean(ua::Boolean),               // Data type ns=0;i=1
181            SByte(ua::SByte),                   // Data type ns=0;i=2
182            Byte(ua::Byte),                     // Data type ns=0;i=3
183            Int16(ua::Int16),                   // Data type ns=0;i=4
184            UInt16(ua::UInt16),                 // Data type ns=0;i=5
185            Int32(ua::Int32),                   // Data type ns=0;i=6
186            UInt32(ua::UInt32),                 // Data type ns=0;i=7
187            Int64(ua::Int64),                   // Data type ns=0;i=8
188            UInt64(ua::UInt64),                 // Data type ns=0;i=9
189            Float(ua::Float),                   // Data type ns=0;i=10
190            Double(ua::Double),                 // Data type ns=0;i=11
191            String(ua::String),                 // Data type ns=0;i=12
192            DateTime(ua::DateTime),             // Data type ns=0;i=13
193            Guid(ua::Guid),                     // Data type ns=0;i=14
194            ByteString(ua::ByteString),         // Data type ns=0;i=15
195            NodeId(ua::NodeId),                 // Data type ns=0;i=17
196            ExpandedNodeId(ua::ExpandedNodeId), // Data type ns=0;i=18
197            StatusCode(ua::StatusCode),         // Data type ns=0;i=19
198            QualifiedName(ua::QualifiedName),   // Data type ns=0;i=20
199            LocalizedText(ua::LocalizedText),   // Data type ns=0;i=21
200            Structure(ua::ExtensionObject),     // Data type ns=0;i=22
201            Enumeration(ua::Enumeration),       // Data type ns=0;i=29
202            Argument(ua::Argument),             // Data type ns=0;i=296
203        );
204
205        VariantValue::Scalar(ScalarValue::Unsupported)
206    }
207
208    #[cfg(feature = "serde")]
209    #[must_use]
210    pub fn json(&self) -> Option<serde_json::Value> {
211        serde_json::to_value(self).ok()
212    }
213}
214
215#[cfg(feature = "serde")]
216impl serde::Serialize for Variant {
217    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
218    where
219        S: serde::Serializer,
220    {
221        macro_rules! serialize {
222            ($self:ident, $serializer:ident, [$( $( #[cfg($cfg: meta)] )? $name:ident ),* $(,)?] $(,)?) => {
223                $(
224                    $( #[cfg($cfg)] )?
225                    if let Some(value) = self.as_scalar::<$crate::ua::$name>() {
226                        return <$crate::ua::$name as serde::Serialize>::serialize(value, serializer);
227                    }
228
229                    $( #[cfg($cfg)] )?
230                    if let Some(value) = self.to_array::<$crate::ua::$name>() {
231                        // TODO: Avoid `to_array()`, borrow `value` from `self` instead of copying.
232                        return <ua::Array<$crate::ua::$name> as serde::Serialize>::serialize(&value, serializer);
233                    }
234                )*
235            };
236        }
237
238        serialize!(
239            self,
240            serializer,
241            [
242                Boolean, // Data type ns=0;i=1
243                SByte,   // Data type ns=0;i=2
244                Byte,    // Data type ns=0;i=3
245                Int16,   // Data type ns=0;i=4
246                UInt16,  // Data type ns=0;i=5
247                Int32,   // Data type ns=0;i=6
248                UInt32,  // Data type ns=0;i=7
249                Int64,   // Data type ns=0;i=8
250                UInt64,  // Data type ns=0;i=9
251                Float,   // Data type ns=0;i=10
252                Double,  // Data type ns=0;i=11
253                String,  // Data type ns=0;i=12
254                #[cfg(feature = "time")]
255                DateTime, // Data type ns=0;i=13
256                #[cfg(feature = "uuid")]
257                Guid, // Data type ns=0;i=14
258                ByteString, // Data type ns=0;i=15
259                NodeId,  // Data type ns=0;i=17
260            ],
261        );
262
263        // The following types are deliberately missing from the list above because we don't have a
264        // good serialization for them (yet):
265        //
266        // - ExpandedNodeId, // Data type ns=0;i=18
267        // - StatusCode,     // Data type ns=0;i=19
268        // - QualifiedName,  // Data type ns=0;i=20
269        // - LocalizedText,  // Data type ns=0;i=21
270        // - Structure,      // Data type ns=0;i=22
271        // - Enumeration,    // Data type ns=0;i=29
272        // - Argument,       // Data type ns=0;i=296
273
274        Err(serde::ser::Error::custom("non-primitive value in Variant"))
275    }
276}
277
278#[cfg(test)]
279mod tests {
280    use open62541_sys::{
281        UA_NS0ID_BOOLEAN, UA_NS0ID_BYTE, UA_NS0ID_INT16, UA_NS0ID_INT64, UA_NS0ID_UINT32,
282    };
283
284    use crate::{DataType as _, ValueType, ua};
285
286    #[test]
287    fn type_empty() {
288        let ua_variant = ua::Variant::init();
289        let type_id = ua_variant.type_id();
290        assert_eq!(type_id, None);
291        let value_type = ua_variant.value_type();
292        assert_eq!(value_type, None);
293    }
294
295    #[test]
296    fn type_boolean() {
297        let ua_bool = ua::Boolean::new(true);
298        let ua_variant = ua::Variant::scalar(ua_bool);
299        let type_id = ua_variant.type_id();
300        assert_eq!(type_id, Some(&ua::NodeId::ns0(UA_NS0ID_BOOLEAN)));
301        let value_type = ua_variant.value_type();
302        assert_eq!(value_type, Some(ValueType::Boolean));
303    }
304
305    #[test]
306    fn type_int() {
307        // Byte
308        let ua_byte = ua::Byte::new(42);
309        let ua_variant = ua::Variant::scalar(ua_byte);
310        let type_id = ua_variant.type_id();
311        assert_eq!(type_id, Some(&ua::NodeId::ns0(UA_NS0ID_BYTE)));
312        let value_type = ua_variant.value_type();
313        assert_eq!(value_type, Some(ValueType::Byte));
314
315        // Int16
316        let ua_int16 = ua::Int16::new(-12345);
317        let ua_variant = ua::Variant::scalar(ua_int16);
318        let type_id = ua_variant.type_id();
319        assert_eq!(type_id, Some(&ua::NodeId::ns0(UA_NS0ID_INT16)));
320        let value_type = ua_variant.value_type();
321        assert_eq!(value_type, Some(ValueType::Int16));
322
323        // UInt32
324        let ua_uint32 = ua::UInt32::new(123_456_789);
325        let ua_variant = ua::Variant::scalar(ua_uint32);
326        let type_id = ua_variant.type_id();
327        assert_eq!(type_id, Some(&ua::NodeId::ns0(UA_NS0ID_UINT32)));
328        let value_type = ua_variant.value_type();
329        assert_eq!(value_type, Some(ValueType::UInt32));
330
331        // Int64
332        let ua_int64 = ua::Int64::new(-7_077_926_753_204_279_296);
333        let ua_variant = ua::Variant::scalar(ua_int64);
334        let type_id = ua_variant.type_id();
335        assert_eq!(type_id, Some(&ua::NodeId::ns0(UA_NS0ID_INT64)));
336        let value_type = ua_variant.value_type();
337        assert_eq!(value_type, Some(ValueType::Int64));
338    }
339
340    #[test]
341    fn array_ops() {
342        let ua_array = ua::Array::from_slice(&[1, 2, 3].map(ua::Byte::new));
343        let ua_variant = ua::Variant::array(ua_array);
344        let type_id = ua_variant.type_id();
345        assert_eq!(type_id, Some(&ua::NodeId::ns0(UA_NS0ID_BYTE)));
346        let value_type = ua_variant.value_type();
347        assert_eq!(value_type, Some(ValueType::Byte));
348
349        assert!(ua_variant.to_array::<ua::String>().is_none());
350        let ua_array: ua::Array<ua::Byte> = ua_variant.to_array().unwrap();
351        assert_eq!(
352            vec![ua::Byte::new(1), ua::Byte::new(2), ua::Byte::new(3)],
353            ua_array.into_vec(),
354        );
355    }
356
357    #[test]
358    fn compare_variant() {
359        // Variants of same type compare as expected.
360        //
361        let variant_1 = ua::Variant::scalar(ua::Byte::new(123));
362        let variant_2 = ua::Variant::scalar(ua::Byte::new(23));
363        let variant_3 = ua::Variant::scalar(ua::Byte::new(23));
364
365        assert_eq!(variant_1, variant_1);
366        assert_ne!(variant_1, variant_2);
367        assert_eq!(variant_2, variant_3);
368
369        // Variants of different type are never equal.
370        //
371        let variant_1 = ua::Variant::scalar(ua::Int16::new(123));
372        let variant_2 = ua::Variant::scalar(ua::Int32::new(123));
373
374        assert_ne!(variant_1, variant_2);
375
376        // Array variants compare their inner elements.
377        //
378        let array_1 = ua::Array::from_slice(&[1, 2, 3].map(ua::Byte::new));
379        let variant_1 = ua::Variant::array(array_1);
380        let array_2 = ua::Array::from_slice(&[2, 3, 4].map(ua::Byte::new));
381        let variant_2 = ua::Variant::array(array_2);
382        let array_3 = ua::Array::from_slice(&[2, 3, 4].map(ua::Byte::new));
383        let variant_3 = ua::Variant::array(array_3);
384
385        assert_eq!(variant_1, variant_1);
386        assert_ne!(variant_1, variant_2);
387        assert_eq!(variant_2, variant_3);
388
389        let array_1 = ua::Array::from_slice(&[1, 2, 3].map(ua::Int16::new));
390        let variant_1 = ua::Variant::array(array_1);
391        let array_2 = ua::Array::from_slice(&[1, 2, 3].map(ua::Int32::new));
392        let variant_2 = ua::Variant::array(array_2);
393
394        assert_ne!(variant_1, variant_2);
395    }
396
397    #[cfg(feature = "serde")]
398    mod serde {
399        use crate::ua;
400
401        #[test]
402        fn serialize_bool() {
403            // Value `true`
404            let ua_bool = ua::Boolean::new(true);
405            let ua_variant = ua::Variant::scalar(ua_bool);
406            let json = serde_json::to_string(&ua_variant).unwrap();
407            assert_eq!("true", json);
408
409            // Value `false`
410            let ua_bool = ua::Boolean::new(false);
411            let ua_variant = ua::Variant::scalar(ua_bool);
412            let json = serde_json::to_string(&ua_variant).unwrap();
413            assert_eq!("false", json);
414        }
415
416        #[test]
417        fn serialize_int() {
418            // Byte (unsigned)
419            let ua_byte = ua::Byte::new(42);
420            let ua_variant = ua::Variant::scalar(ua_byte);
421            let json = serde_json::to_string(&ua_variant).unwrap();
422            assert_eq!("42", json);
423
424            // Int16 (signed)
425            let ua_int16 = ua::Int16::new(-12345);
426            let ua_variant = ua::Variant::scalar(ua_int16);
427            let json = serde_json::to_string(&ua_variant).unwrap();
428            assert_eq!("-12345", json);
429
430            // UInt32 (unsigned)
431            let ua_uint32 = ua::UInt32::new(123_456_789);
432            let ua_variant = ua::Variant::scalar(ua_uint32);
433            let json = serde_json::to_string(&ua_variant).unwrap();
434            assert_eq!("123456789", json);
435
436            // Int64 (signed)
437            let ua_int64 = ua::Int64::new(-7_077_926_753_204_279_296);
438            let ua_variant = ua::Variant::scalar(ua_int64);
439            let json = serde_json::to_string(&ua_variant).unwrap();
440            assert_eq!("-7077926753204279296", json);
441        }
442
443        #[test]
444        fn serialize_float() {
445            // Float
446            let ua_float = ua::Float::new(123.4567);
447            let ua_variant = ua::Variant::scalar(ua_float);
448            let json = serde_json::to_string(&ua_variant).unwrap();
449            assert_eq!("123.4567", json);
450
451            // Double
452            let ua_double = ua::Double::new(-98_765_432.1);
453            let ua_variant = ua::Variant::scalar(ua_double);
454            let json = serde_json::to_string(&ua_variant).unwrap();
455            assert_eq!("-98765432.1", json);
456        }
457
458        #[test]
459        fn serialize_string() {
460            // Empty string
461            let ua_string = ua::String::new("").unwrap();
462            let ua_variant = ua::Variant::scalar(ua_string);
463            let json = serde_json::to_string(&ua_variant).unwrap();
464            assert_eq!(r#""""#, json);
465
466            // Short string
467            let ua_string = ua::String::new("lorem ipsum").unwrap();
468            let ua_variant = ua::Variant::scalar(ua_string);
469            let json = serde_json::to_string(&ua_variant).unwrap();
470            assert_eq!(r#""lorem ipsum""#, json);
471
472            // Special characters
473            let ua_string = ua::String::new(r#"a'b"c{dẞe"#).unwrap();
474            let ua_variant = ua::Variant::scalar(ua_string);
475            let json = serde_json::to_string(&ua_variant).unwrap();
476            assert_eq!(r#""a'b\"c{dẞe""#, json);
477        }
478
479        #[cfg(feature = "time")]
480        #[test]
481        fn serialize_datetime() {
482            // Minute precision
483            let datetime = time::macros::utc_datetime!(2024-02-09 16:48);
484            let ua_datetime = ua::DateTime::try_from(datetime).unwrap();
485            let ua_variant = ua::Variant::scalar(ua_datetime);
486            let json = serde_json::to_string(&ua_variant).unwrap();
487            assert_eq!(r#""2024-02-09T16:48:00Z""#, json);
488
489            // Microsecond precision
490            let datetime = time::macros::utc_datetime!(2024-02-09 16:48:52.123456);
491            let ua_datetime = ua::DateTime::try_from(datetime).unwrap();
492            let ua_variant = ua::Variant::scalar(ua_datetime);
493            let json = serde_json::to_string(&ua_variant).unwrap();
494            assert_eq!(r#""2024-02-09T16:48:52.123456Z""#, json);
495        }
496
497        #[cfg(feature = "uuid")]
498        #[test]
499        fn serialize_guid() {
500            let uuid = uuid::Uuid::parse_str("12191b7c-4f71-4e7b-9ac7-d4989bb1b373").unwrap();
501            let ua_guid = ua::Guid::from(uuid);
502            let ua_variant = ua::Variant::scalar(ua_guid);
503            let json = serde_json::to_string(&ua_variant).unwrap();
504            assert_eq!(r#""12191b7c-4f71-4e7b-9ac7-d4989bb1b373""#, json);
505        }
506
507        #[test]
508        fn serialize_array() {
509            let ua_array = ua::Array::from_slice(&[1, 2, 3].map(ua::Byte::new));
510            let ua_variant = ua::Variant::array(ua_array);
511            let json = serde_json::to_string(&ua_variant).unwrap();
512            assert_eq!("[1,2,3]", json);
513
514            let ua_array = ua::Array::from_slice(&[
515                ua::String::new("lorem").unwrap(),
516                ua::String::new(r#"ip"sum"#).unwrap(),
517            ]);
518            let ua_variant = ua::Variant::array(ua_array);
519            let json = serde_json::to_string(&ua_variant).unwrap();
520            assert_eq!(r#"["lorem","ip\"sum"]"#, json);
521        }
522    }
523}