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 #[must_use]
15 pub fn scalar<T: DataType>(value: T) -> Self {
16 let mut variant = Self::init();
17 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 #[must_use]
28 pub fn array<T: DataType>(value: ua::Array<T>) -> Self {
29 let mut variant = Self::init();
30 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 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 #[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 #[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 .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 .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 .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 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 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 }
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 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 check!(
180 Boolean(ua::Boolean), SByte(ua::SByte), Byte(ua::Byte), Int16(ua::Int16), UInt16(ua::UInt16), Int32(ua::Int32), UInt32(ua::UInt32), Int64(ua::Int64), UInt64(ua::UInt64), Float(ua::Float), Double(ua::Double), String(ua::String), DateTime(ua::DateTime), Guid(ua::Guid), ByteString(ua::ByteString), NodeId(ua::NodeId), ExpandedNodeId(ua::ExpandedNodeId), StatusCode(ua::StatusCode), QualifiedName(ua::QualifiedName), LocalizedText(ua::LocalizedText), Structure(ua::ExtensionObject), Enumeration(ua::Enumeration), Argument(ua::Argument), );
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 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, SByte, Byte, Int16, UInt16, Int32, UInt32, Int64, UInt64, Float, Double, String, #[cfg(feature = "time")]
255 DateTime, #[cfg(feature = "uuid")]
257 Guid, ByteString, NodeId, ],
261 );
262
263 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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}