Skip to main content

opcua/types/
variant.rs

1// OPCUA for Rust
2// SPDX-License-Identifier: MPL-2.0
3// Copyright (C) 2017-2022 Adam Lock
4
5//! Contains the most of the implementation of `Variant`. Some substantial chunks like JSON serialization
6//! are moved off into their own files due to the complexity of this functionality.
7
8use std::{
9    convert::TryFrom,
10    fmt,
11    io::{Read, Write},
12    str::FromStr,
13    {i16, i32, i64, i8, u16, u32, u64, u8},
14};
15
16use crate::types::{
17    array::*,
18    byte_string::ByteString,
19    date_time::DateTime,
20    encoding::*,
21    expanded_node_id::ExpandedNodeId,
22    extension_object::ExtensionObject,
23    guid::Guid,
24    localized_text::LocalizedText,
25    node_id::NodeId,
26    node_ids::DataTypeId,
27    numeric_range::NumericRange,
28    qualified_name::QualifiedName,
29    status_codes::StatusCode,
30    string::{UAString, XmlElement},
31    variant_type_id::*,
32    DataValue, DiagnosticInfo,
33};
34
35/// A `Variant` holds built-in OPC UA data types, including single and multi dimensional arrays,
36/// data values and extension objects.
37///
38/// As variants may be passed around a lot on the stack, Boxes are used for more complex types to
39/// keep the size of this type down a bit, especially when used in arrays.
40#[derive(PartialEq, Debug, Clone)]
41pub enum Variant {
42    /// Empty type has no value. It is equivalent to a Null value (part 6 5.1.6)
43    Empty,
44    /// Boolean
45    Boolean(bool),
46    /// Signed byte
47    SByte(i8),
48    /// Unsigned byte
49    Byte(u8),
50    /// Signed 16-bit int
51    Int16(i16),
52    /// Unsigned 16-bit int
53    UInt16(u16),
54    /// Signed 32-bit int
55    Int32(i32),
56    /// Unsigned 32-bit int
57    UInt32(u32),
58    /// Signed 64-bit int
59    Int64(i64),
60    /// Unsigned 64-bit int
61    UInt64(u64),
62    /// Float
63    Float(f32),
64    /// Double
65    Double(f64),
66    /// String
67    String(UAString),
68    /// DateTime
69    DateTime(Box<DateTime>),
70    /// Guid
71    Guid(Box<Guid>),
72    /// StatusCode
73    StatusCode(StatusCode),
74    /// ByteString
75    ByteString(ByteString),
76    /// XmlElement
77    XmlElement(XmlElement),
78    /// QualifiedName
79    QualifiedName(Box<QualifiedName>),
80    /// LocalizedText
81    LocalizedText(Box<LocalizedText>),
82    /// NodeId
83    NodeId(Box<NodeId>),
84    /// ExpandedNodeId
85    ExpandedNodeId(Box<ExpandedNodeId>),
86    /// ExtensionObject
87    ExtensionObject(Box<ExtensionObject>),
88    // Variant
89    Variant(Box<Variant>),
90    // DataValue
91    DataValue(Box<DataValue>),
92    // Diagnostics
93    DiagnosticInfo(Box<DiagnosticInfo>),
94    /// Single dimension array which can contain any scalar type, all the same type. Nested
95    /// arrays will be rejected.
96    Array(Box<Array>),
97}
98
99macro_rules! impl_from_variant_for {
100    ($tp: ty, $vt: expr, $venum: path) => {
101        impl TryFrom<Variant> for $tp {
102            type Error = ();
103            fn try_from(v: Variant) -> Result<Self, Self::Error> {
104                let casted = v.cast($vt);
105                if let $venum(x) = casted {
106                    Ok(x)
107                } else {
108                    Err(())
109                }
110            }
111        }
112    };
113}
114
115macro_rules! impl_from_variant_for_array {
116    ($tp: ty, $vt: expr, $venum: path) => {
117        impl<const N: usize> TryFrom<Variant> for [$tp; N] {
118            type Error = ();
119            fn try_from(v: Variant) -> Result<Self, Self::Error> {
120                if let Variant::Array(arr) = v {
121                    let mut result = Vec::with_capacity(N);
122                    for val in arr.values {
123                        if result.len() == N {
124                            break;
125                        }
126                        let casted = val.cast($vt);
127                        if let $venum(x) = casted {
128                            result.push(x);
129                        } else {
130                            return Err(());
131                        }
132                    }
133                    result.try_into().map_err(|_| ())
134                } else {
135                    Err(())
136                }
137            }
138        }
139    };
140}
141
142impl_from_variant_for!(bool, VariantTypeId::Boolean, Variant::Boolean);
143impl_from_variant_for!(u8, VariantTypeId::Byte, Variant::Byte);
144impl_from_variant_for!(i8, VariantTypeId::SByte, Variant::SByte);
145impl_from_variant_for!(i16, VariantTypeId::Int16, Variant::Int16);
146impl_from_variant_for!(i32, VariantTypeId::Int32, Variant::Int32);
147impl_from_variant_for!(i64, VariantTypeId::Int64, Variant::Int64);
148impl_from_variant_for!(u16, VariantTypeId::UInt16, Variant::UInt16);
149impl_from_variant_for!(u32, VariantTypeId::UInt32, Variant::UInt32);
150impl_from_variant_for!(u64, VariantTypeId::UInt64, Variant::UInt64);
151impl_from_variant_for!(f32, VariantTypeId::Float, Variant::Float);
152impl_from_variant_for!(f64, VariantTypeId::Double, Variant::Double);
153
154impl_from_variant_for_array!(bool, VariantTypeId::Boolean, Variant::Boolean);
155impl_from_variant_for_array!(u8, VariantTypeId::Byte, Variant::Byte);
156impl_from_variant_for_array!(i8, VariantTypeId::SByte, Variant::SByte);
157impl_from_variant_for_array!(i16, VariantTypeId::Int16, Variant::Int16);
158impl_from_variant_for_array!(i32, VariantTypeId::Int32, Variant::Int32);
159impl_from_variant_for_array!(i64, VariantTypeId::Int64, Variant::Int64);
160impl_from_variant_for_array!(u16, VariantTypeId::UInt16, Variant::UInt16);
161impl_from_variant_for_array!(u32, VariantTypeId::UInt32, Variant::UInt32);
162impl_from_variant_for_array!(u64, VariantTypeId::UInt64, Variant::UInt64);
163impl_from_variant_for_array!(f32, VariantTypeId::Float, Variant::Float);
164impl_from_variant_for_array!(f64, VariantTypeId::Double, Variant::Double);
165
166impl From<()> for Variant {
167    fn from(_: ()) -> Self {
168        Variant::Empty
169    }
170}
171
172impl From<bool> for Variant {
173    fn from(v: bool) -> Self {
174        Variant::Boolean(v)
175    }
176}
177
178impl From<u8> for Variant {
179    fn from(v: u8) -> Self {
180        Variant::Byte(v)
181    }
182}
183
184impl From<i8> for Variant {
185    fn from(v: i8) -> Self {
186        Variant::SByte(v)
187    }
188}
189
190impl From<i16> for Variant {
191    fn from(v: i16) -> Self {
192        Variant::Int16(v)
193    }
194}
195
196impl From<u16> for Variant {
197    fn from(v: u16) -> Self {
198        Variant::UInt16(v)
199    }
200}
201
202impl From<i32> for Variant {
203    fn from(v: i32) -> Self {
204        Variant::Int32(v)
205    }
206}
207
208impl From<u32> for Variant {
209    fn from(v: u32) -> Self {
210        Variant::UInt32(v)
211    }
212}
213
214impl From<i64> for Variant {
215    fn from(v: i64) -> Self {
216        Variant::Int64(v)
217    }
218}
219
220impl From<u64> for Variant {
221    fn from(v: u64) -> Self {
222        Variant::UInt64(v)
223    }
224}
225
226impl From<f32> for Variant {
227    fn from(v: f32) -> Self {
228        Variant::Float(v)
229    }
230}
231
232impl From<f64> for Variant {
233    fn from(v: f64) -> Self {
234        Variant::Double(v)
235    }
236}
237
238impl<'a> From<&'a str> for Variant {
239    fn from(v: &'a str) -> Self {
240        Variant::String(UAString::from(v))
241    }
242}
243
244impl From<String> for Variant {
245    fn from(v: String) -> Self {
246        Variant::String(UAString::from(v))
247    }
248}
249
250impl From<UAString> for Variant {
251    fn from(v: UAString) -> Self {
252        Variant::String(v)
253    }
254}
255
256impl From<DateTime> for Variant {
257    fn from(v: DateTime) -> Self {
258        Variant::DateTime(Box::new(v))
259    }
260}
261
262impl From<Guid> for Variant {
263    fn from(v: Guid) -> Self {
264        Variant::Guid(Box::new(v))
265    }
266}
267
268impl From<StatusCode> for Variant {
269    fn from(v: StatusCode) -> Self {
270        Variant::StatusCode(v)
271    }
272}
273
274impl From<ByteString> for Variant {
275    fn from(v: ByteString) -> Self {
276        Variant::ByteString(v)
277    }
278}
279
280impl From<QualifiedName> for Variant {
281    fn from(v: QualifiedName) -> Self {
282        Variant::QualifiedName(Box::new(v))
283    }
284}
285
286impl From<LocalizedText> for Variant {
287    fn from(v: LocalizedText) -> Self {
288        Variant::LocalizedText(Box::new(v))
289    }
290}
291
292impl From<NodeId> for Variant {
293    fn from(v: NodeId) -> Self {
294        Variant::NodeId(Box::new(v))
295    }
296}
297
298impl From<ExpandedNodeId> for Variant {
299    fn from(v: ExpandedNodeId) -> Self {
300        Variant::ExpandedNodeId(Box::new(v))
301    }
302}
303
304impl From<ExtensionObject> for Variant {
305    fn from(v: ExtensionObject) -> Self {
306        Variant::ExtensionObject(Box::new(v))
307    }
308}
309
310impl From<DataValue> for Variant {
311    fn from(v: DataValue) -> Self {
312        Variant::DataValue(Box::new(v))
313    }
314}
315
316impl From<DiagnosticInfo> for Variant {
317    fn from(v: DiagnosticInfo) -> Self {
318        Variant::DiagnosticInfo(Box::new(v))
319    }
320}
321
322impl<'a, 'b> From<(VariantTypeId, &'a [&'b str])> for Variant {
323    fn from(v: (VariantTypeId, &'a [&'b str])) -> Self {
324        let values: Vec<Variant> = v.1.iter().map(|v| Variant::from(*v)).collect();
325        let value = Array::new(v.0, values).unwrap();
326        Variant::from(value)
327    }
328}
329
330impl From<(VariantTypeId, Vec<Variant>)> for Variant {
331    fn from(v: (VariantTypeId, Vec<Variant>)) -> Self {
332        let value = Array::new(v.0, v.1).unwrap();
333        Variant::from(value)
334    }
335}
336
337impl From<(VariantTypeId, Vec<Variant>, Vec<u32>)> for Variant {
338    fn from(v: (VariantTypeId, Vec<Variant>, Vec<u32>)) -> Self {
339        let value = Array::new_multi(v.0, v.1, v.2).unwrap();
340        Variant::from(value)
341    }
342}
343
344impl From<Array> for Variant {
345    fn from(v: Array) -> Self {
346        Variant::Array(Box::new(v))
347    }
348}
349
350macro_rules! cast_to_bool {
351    ($value: expr) => {
352        if $value == 1 {
353            true.into()
354        } else if $value == 0 {
355            false.into()
356        } else {
357            Variant::Empty
358        }
359    };
360}
361
362macro_rules! cast_to_integer {
363    ($value: expr, $from: ident, $to: ident) => {
364        {
365            // 64-bit values are the highest supported by OPC UA, so this code will cast
366            // and compare values using signed / unsigned types to determine if they're in range.
367            let valid = if $value < 0 as $from {
368                // Negative values can only go into a signed type and only when the value is greater
369                // or equal to the MIN
370                $to::MIN != 0 && $value as i64 >= $to::MIN as i64
371            } else {
372                // Positive values can only go into the type only when the value is less than or equal
373                // to the MAX.
374                $value as u64 <= $to::MAX as u64
375            };
376            if !valid {
377                // Value is out of range
378                // error!("Value {} is outside of the range of receiving in type {}..{}", $value, $to::MIN, $to::MAX);
379                Variant::Empty
380            } else {
381                ($value as $to).into()
382            }
383        }
384    }
385}
386
387macro_rules! from_array_to_variant_impl {
388    ($encoding_mask: expr, $rtype: ident) => {
389        impl<'a> From<&'a Vec<$rtype>> for Variant {
390            fn from(v: &'a Vec<$rtype>) -> Self {
391                Variant::from(v.as_slice())
392            }
393        }
394
395        impl From<Vec<$rtype>> for Variant {
396            fn from(v: Vec<$rtype>) -> Self {
397                Variant::from(v.as_slice())
398            }
399        }
400
401        impl<'a> From<&'a [$rtype]> for Variant {
402            fn from(v: &'a [$rtype]) -> Self {
403                let array: Vec<Variant> = v.iter().map(|v| Variant::from(v.clone())).collect();
404                Variant::try_from(($encoding_mask, array)).unwrap()
405            }
406        }
407    };
408}
409
410from_array_to_variant_impl!(VariantTypeId::String, String);
411from_array_to_variant_impl!(VariantTypeId::Boolean, bool);
412from_array_to_variant_impl!(VariantTypeId::SByte, i8);
413from_array_to_variant_impl!(VariantTypeId::Byte, u8);
414from_array_to_variant_impl!(VariantTypeId::Int16, i16);
415from_array_to_variant_impl!(VariantTypeId::UInt16, u16);
416from_array_to_variant_impl!(VariantTypeId::Int32, i32);
417from_array_to_variant_impl!(VariantTypeId::UInt32, u32);
418from_array_to_variant_impl!(VariantTypeId::Int64, i64);
419from_array_to_variant_impl!(VariantTypeId::UInt64, u64);
420from_array_to_variant_impl!(VariantTypeId::Float, f32);
421from_array_to_variant_impl!(VariantTypeId::Double, f64);
422
423/// This macro tries to return a `Vec<foo>` from a `Variant::Array<Variant::Foo>>`, e.g.
424/// If the Variant holds
425macro_rules! try_from_variant_to_array_impl {
426    ($rtype: ident, $vtype: ident) => {
427        impl TryFrom<&Variant> for Vec<$rtype> {
428            type Error = ();
429
430            fn try_from(value: &Variant) -> Result<Self, Self::Error> {
431                match value {
432                    Variant::Array(ref array) => {
433                        let values = &array.values;
434                        if !values_are_of_type(values, VariantTypeId::$vtype) {
435                            Err(())
436                        } else {
437                            Ok(values
438                                .iter()
439                                .map(|v| {
440                                    if let Variant::$vtype(v) = v {
441                                        *v
442                                    } else {
443                                        panic!()
444                                    }
445                                })
446                                .collect())
447                        }
448                    }
449                    _ => Err(()),
450                }
451            }
452        }
453    };
454}
455
456// These are implementations of TryFrom which will attempt to transform a single dimension array
457// in a Variant to the respective Vec<T> defined in the macro. All the variants must be of the correct
458// type or the impl will return with an error.
459
460try_from_variant_to_array_impl!(bool, Boolean);
461try_from_variant_to_array_impl!(i8, SByte);
462try_from_variant_to_array_impl!(u8, Byte);
463try_from_variant_to_array_impl!(i16, Int16);
464try_from_variant_to_array_impl!(u16, UInt16);
465try_from_variant_to_array_impl!(i32, Int32);
466try_from_variant_to_array_impl!(u32, UInt32);
467try_from_variant_to_array_impl!(i64, Int64);
468try_from_variant_to_array_impl!(u64, UInt64);
469try_from_variant_to_array_impl!(f32, Float);
470try_from_variant_to_array_impl!(f64, Double);
471
472impl BinaryEncoder<Variant> for Variant {
473    fn byte_len(&self) -> usize {
474        let mut size: usize = 0;
475
476        // Encoding mask
477        size += 1;
478
479        // Value itself
480        size += match self {
481            Variant::Empty => 0,
482            Variant::Boolean(value) => value.byte_len(),
483            Variant::SByte(value) => value.byte_len(),
484            Variant::Byte(value) => value.byte_len(),
485            Variant::Int16(value) => value.byte_len(),
486            Variant::UInt16(value) => value.byte_len(),
487            Variant::Int32(value) => value.byte_len(),
488            Variant::UInt32(value) => value.byte_len(),
489            Variant::Int64(value) => value.byte_len(),
490            Variant::UInt64(value) => value.byte_len(),
491            Variant::Float(value) => value.byte_len(),
492            Variant::Double(value) => value.byte_len(),
493            Variant::String(value) => value.byte_len(),
494            Variant::DateTime(value) => value.byte_len(),
495            Variant::Guid(value) => value.byte_len(),
496            Variant::ByteString(value) => value.byte_len(),
497            Variant::XmlElement(value) => value.byte_len(),
498            Variant::NodeId(value) => value.byte_len(),
499            Variant::ExpandedNodeId(value) => value.byte_len(),
500            Variant::StatusCode(value) => value.byte_len(),
501            Variant::QualifiedName(value) => value.byte_len(),
502            Variant::LocalizedText(value) => value.byte_len(),
503            Variant::ExtensionObject(value) => value.byte_len(),
504            Variant::DataValue(value) => value.byte_len(),
505            Variant::Variant(value) => value.byte_len(),
506            Variant::DiagnosticInfo(value) => value.byte_len(),
507            Variant::Array(array) => {
508                // Array length
509                let mut size = 4;
510                // Size of each value
511                size += array
512                    .values
513                    .iter()
514                    .map(Variant::byte_len_variant_value)
515                    .sum::<usize>();
516                if let Some(ref dimensions) = array.dimensions {
517                    // Dimensions (size + num elements)
518                    size += 4 + dimensions.len() * 4;
519                }
520                size
521            }
522        };
523        size
524    }
525
526    fn encode<S: Write>(&self, stream: &mut S) -> EncodingResult<usize> {
527        let mut size: usize = 0;
528
529        // Encoding mask will include the array bits if applicable for the type
530        let encoding_mask = self.encoding_mask();
531        size += write_u8(stream, encoding_mask)?;
532
533        size += match self {
534            Variant::Empty => 0,
535            Variant::Boolean(value) => value.encode(stream)?,
536            Variant::SByte(value) => value.encode(stream)?,
537            Variant::Byte(value) => value.encode(stream)?,
538            Variant::Int16(value) => value.encode(stream)?,
539            Variant::UInt16(value) => value.encode(stream)?,
540            Variant::Int32(value) => value.encode(stream)?,
541            Variant::UInt32(value) => value.encode(stream)?,
542            Variant::Int64(value) => value.encode(stream)?,
543            Variant::UInt64(value) => value.encode(stream)?,
544            Variant::Float(value) => value.encode(stream)?,
545            Variant::Double(value) => value.encode(stream)?,
546            Variant::String(value) => value.encode(stream)?,
547            Variant::DateTime(value) => value.encode(stream)?,
548            Variant::Guid(value) => value.encode(stream)?,
549            Variant::ByteString(value) => value.encode(stream)?,
550            Variant::XmlElement(value) => value.encode(stream)?,
551            Variant::NodeId(value) => value.encode(stream)?,
552            Variant::ExpandedNodeId(value) => value.encode(stream)?,
553            Variant::StatusCode(value) => value.encode(stream)?,
554            Variant::QualifiedName(value) => value.encode(stream)?,
555            Variant::LocalizedText(value) => value.encode(stream)?,
556            Variant::ExtensionObject(value) => value.encode(stream)?,
557            Variant::DataValue(value) => value.encode(stream)?,
558            Variant::Variant(value) => value.encode(stream)?,
559            Variant::DiagnosticInfo(value) => value.encode(stream)?,
560            Variant::Array(array) => {
561                let mut size = write_i32(stream, array.values.len() as i32)?;
562                for value in array.values.iter() {
563                    size += Variant::encode_variant_value(stream, value)?;
564                }
565                if let Some(ref dimensions) = array.dimensions {
566                    // Note array dimensions are encoded as Int32 even though they are presented
567                    // as UInt32 through attribute.
568
569                    // Encode dimensions length
570                    size += write_i32(stream, dimensions.len() as i32)?;
571                    // Encode dimensions
572                    for dimension in dimensions {
573                        size += write_i32(stream, *dimension as i32)?;
574                    }
575                }
576                size
577            }
578        };
579        assert_eq!(size, self.byte_len());
580        Ok(size)
581    }
582
583    fn decode<S: Read>(stream: &mut S, decoding_options: &DecodingOptions) -> EncodingResult<Self> {
584        let encoding_mask = u8::decode(stream, decoding_options)?;
585        let element_encoding_mask = encoding_mask & !EncodingMask::ARRAY_MASK;
586
587        // IMPORTANT NOTE: Arrays are constructed through Array::new_multi or Array::new_single
588        // to correctly process failures. Don't use Variant::from((value_type, values)) since
589        // this will panic & break the runtime. We don't want this when dealing with potentially
590        // malicious data.
591
592        // Read array length
593        let array_length = if encoding_mask & EncodingMask::ARRAY_VALUES_BIT != 0 {
594            let array_length = i32::decode(stream, decoding_options)?;
595            if array_length < -1 {
596                error!("Invalid array_length {}", array_length);
597                return Err(StatusCode::BadDecodingError);
598            }
599
600            // null array of type for length 0 and -1 so it doesn't fail for length 0
601            if array_length <= 0 {
602                let value_type_id = VariantTypeId::from_encoding_mask(element_encoding_mask)?;
603                return Array::new_multi(value_type_id, Vec::new(), Vec::new()).map(Variant::from);
604            }
605            array_length
606        } else {
607            -1
608        };
609
610        // Read the value(s). If array length was specified, we assume a single or multi dimension array
611        if array_length > 0 {
612            // Array length in total cannot exceed max array length
613            let array_length = array_length as usize;
614            if array_length > decoding_options.max_array_length {
615                return Err(StatusCode::BadEncodingLimitsExceeded);
616            }
617
618            let mut values: Vec<Variant> = Vec::with_capacity(array_length);
619            for _ in 0..array_length {
620                values.push(Variant::decode_variant_value(
621                    stream,
622                    element_encoding_mask,
623                    decoding_options,
624                )?);
625            }
626            let value_type_id = VariantTypeId::from_encoding_mask(element_encoding_mask)?;
627            if encoding_mask & EncodingMask::ARRAY_DIMENSIONS_BIT != 0 {
628                if let Some(dimensions) = read_array(stream, decoding_options)? {
629                    if dimensions.iter().any(|d| *d == 0) {
630                        error!("Invalid array dimensions");
631                        Err(StatusCode::BadDecodingError)
632                    } else {
633                        // This looks clunky but it's to prevent a panic from malicious data
634                        // causing an overflow panic
635                        let mut array_dimensions_length = 1u32;
636                        for d in &dimensions {
637                            if let Some(v) = array_dimensions_length.checked_mul(*d) {
638                                array_dimensions_length = v;
639                            } else {
640                                error!("Array dimension overflow!");
641                                return Err(StatusCode::BadDecodingError);
642                            }
643                        }
644                        if array_dimensions_length != array_length as u32 {
645                            error!(
646                                "Array dimensions does not match array length {}",
647                                array_length
648                            );
649                            Err(StatusCode::BadDecodingError)
650                        } else {
651                            // Note Array::new_multi can fail
652                            Array::new_multi(value_type_id, values, dimensions).map(Variant::from)
653                        }
654                    }
655                } else {
656                    error!("No array dimensions despite the bit flag being set");
657                    Err(StatusCode::BadDecodingError)
658                }
659            } else {
660                // Note Array::new_single can fail
661                Array::new(value_type_id, values).map(Variant::from)
662            }
663        } else if encoding_mask & EncodingMask::ARRAY_DIMENSIONS_BIT != 0 {
664            error!("Array dimensions bit specified without any values");
665            Err(StatusCode::BadDecodingError)
666        } else {
667            // Read a single variant
668            Variant::decode_variant_value(stream, element_encoding_mask, decoding_options)
669        }
670    }
671}
672
673impl Default for Variant {
674    fn default() -> Self {
675        Variant::Empty
676    }
677}
678
679/// This implementation is mainly for debugging / convenience purposes, to eliminate some of the
680/// noise in common types from using the Debug trait.
681impl fmt::Display for Variant {
682    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
683        match self {
684            Variant::SByte(v) => write!(f, "{}", v),
685            Variant::Byte(v) => write!(f, "{}", v),
686            Variant::Int16(v) => write!(f, "{}", v),
687            Variant::UInt16(v) => write!(f, "{}", v),
688            Variant::Int32(v) => write!(f, "{}", v),
689            Variant::UInt32(v) => write!(f, "{}", v),
690            Variant::Int64(v) => write!(f, "{}", v),
691            Variant::UInt64(v) => write!(f, "{}", v),
692            Variant::Float(v) => write!(f, "{}", v),
693            Variant::Double(v) => write!(f, "{}", v),
694            Variant::Boolean(v) => write!(f, "{}", v),
695            Variant::String(ref v) => write!(f, "{}", v),
696            Variant::Guid(ref v) => write!(f, "{}", v),
697            Variant::DateTime(ref v) => write!(f, "{}", v),
698            Variant::NodeId(ref v) => write!(f, "{}", v),
699            Variant::ExpandedNodeId(ref v) => write!(f, "{}", v),
700            Variant::Variant(ref v) => write!(f, "Variant({})", v),
701            value => write!(f, "{:?}", value),
702        }
703    }
704}
705
706impl Variant {
707    /// Test the flag (convenience method)
708    pub fn test_encoding_flag(encoding_mask: u8, flag: u8) -> bool {
709        encoding_mask == flag as u8
710    }
711
712    /// Returns the length of just the value, not the encoding flag
713    fn byte_len_variant_value(value: &Variant) -> usize {
714        match value {
715            Variant::Empty => 0,
716            Variant::Boolean(value) => value.byte_len(),
717            Variant::SByte(value) => value.byte_len(),
718            Variant::Byte(value) => value.byte_len(),
719            Variant::Int16(value) => value.byte_len(),
720            Variant::UInt16(value) => value.byte_len(),
721            Variant::Int32(value) => value.byte_len(),
722            Variant::UInt32(value) => value.byte_len(),
723            Variant::Int64(value) => value.byte_len(),
724            Variant::UInt64(value) => value.byte_len(),
725            Variant::Float(value) => value.byte_len(),
726            Variant::Double(value) => value.byte_len(),
727            Variant::String(value) => value.byte_len(),
728            Variant::DateTime(value) => value.byte_len(),
729            Variant::Guid(value) => value.byte_len(),
730            Variant::ByteString(value) => value.byte_len(),
731            Variant::XmlElement(value) => value.byte_len(),
732            Variant::NodeId(value) => value.byte_len(),
733            Variant::ExpandedNodeId(value) => value.byte_len(),
734            Variant::StatusCode(value) => value.byte_len(),
735            Variant::QualifiedName(value) => value.byte_len(),
736            Variant::LocalizedText(value) => value.byte_len(),
737            Variant::ExtensionObject(value) => value.byte_len(),
738            Variant::Variant(value) => value.byte_len(),
739            Variant::DataValue(value) => value.byte_len(),
740            Variant::DiagnosticInfo(value) => value.byte_len(),
741            _ => {
742                error!("Cannot compute length of this type (probably nested array)");
743                0
744            }
745        }
746    }
747
748    /// Encodes just the value, not the encoding flag
749    fn encode_variant_value<S: Write>(stream: &mut S, value: &Variant) -> EncodingResult<usize> {
750        match value {
751            Variant::Empty => Ok(0),
752            Variant::Boolean(value) => value.encode(stream),
753            Variant::SByte(value) => value.encode(stream),
754            Variant::Byte(value) => value.encode(stream),
755            Variant::Int16(value) => value.encode(stream),
756            Variant::UInt16(value) => value.encode(stream),
757            Variant::Int32(value) => value.encode(stream),
758            Variant::UInt32(value) => value.encode(stream),
759            Variant::Int64(value) => value.encode(stream),
760            Variant::UInt64(value) => value.encode(stream),
761            Variant::Float(value) => value.encode(stream),
762            Variant::Double(value) => value.encode(stream),
763            Variant::String(value) => value.encode(stream),
764            Variant::DateTime(value) => value.encode(stream),
765            Variant::Guid(value) => value.encode(stream),
766            Variant::ByteString(value) => value.encode(stream),
767            Variant::XmlElement(value) => value.encode(stream),
768            Variant::NodeId(value) => value.encode(stream),
769            Variant::ExpandedNodeId(value) => value.encode(stream),
770            Variant::StatusCode(value) => value.encode(stream),
771            Variant::QualifiedName(value) => value.encode(stream),
772            Variant::LocalizedText(value) => value.encode(stream),
773            Variant::ExtensionObject(value) => value.encode(stream),
774            Variant::Variant(value) => value.encode(stream),
775            Variant::DataValue(value) => value.encode(stream),
776            Variant::DiagnosticInfo(value) => value.encode(stream),
777            _ => {
778                warn!("Cannot encode this variant value type (probably nested array)");
779                Err(StatusCode::BadEncodingError)
780            }
781        }
782    }
783
784    /// Reads just the variant value from the stream
785    fn decode_variant_value<S: Read>(
786        stream: &mut S,
787        encoding_mask: u8,
788        decoding_options: &DecodingOptions,
789    ) -> EncodingResult<Self> {
790        let result = if encoding_mask == 0 {
791            Variant::Empty
792        } else if Self::test_encoding_flag(encoding_mask, EncodingMask::BOOLEAN) {
793            Self::from(bool::decode(stream, decoding_options)?)
794        } else if Self::test_encoding_flag(encoding_mask, EncodingMask::SBYTE) {
795            Self::from(i8::decode(stream, decoding_options)?)
796        } else if Self::test_encoding_flag(encoding_mask, EncodingMask::BYTE) {
797            Self::from(u8::decode(stream, decoding_options)?)
798        } else if Self::test_encoding_flag(encoding_mask, EncodingMask::INT16) {
799            Self::from(i16::decode(stream, decoding_options)?)
800        } else if Self::test_encoding_flag(encoding_mask, EncodingMask::UINT16) {
801            Self::from(u16::decode(stream, decoding_options)?)
802        } else if Self::test_encoding_flag(encoding_mask, EncodingMask::INT32) {
803            Self::from(i32::decode(stream, decoding_options)?)
804        } else if Self::test_encoding_flag(encoding_mask, EncodingMask::UINT32) {
805            Self::from(u32::decode(stream, decoding_options)?)
806        } else if Self::test_encoding_flag(encoding_mask, EncodingMask::INT64) {
807            Self::from(i64::decode(stream, decoding_options)?)
808        } else if Self::test_encoding_flag(encoding_mask, EncodingMask::UINT64) {
809            Self::from(u64::decode(stream, decoding_options)?)
810        } else if Self::test_encoding_flag(encoding_mask, EncodingMask::FLOAT) {
811            Self::from(f32::decode(stream, decoding_options)?)
812        } else if Self::test_encoding_flag(encoding_mask, EncodingMask::DOUBLE) {
813            Self::from(f64::decode(stream, decoding_options)?)
814        } else if Self::test_encoding_flag(encoding_mask, EncodingMask::STRING) {
815            Self::from(UAString::decode(stream, decoding_options)?)
816        } else if Self::test_encoding_flag(encoding_mask, EncodingMask::DATE_TIME) {
817            Self::from(DateTime::decode(stream, decoding_options)?)
818        } else if Self::test_encoding_flag(encoding_mask, EncodingMask::GUID) {
819            Self::from(Guid::decode(stream, decoding_options)?)
820        } else if Self::test_encoding_flag(encoding_mask, EncodingMask::BYTE_STRING) {
821            Self::from(ByteString::decode(stream, decoding_options)?)
822        } else if Self::test_encoding_flag(encoding_mask, EncodingMask::XML_ELEMENT) {
823            // Force the type to be XmlElement since its typedef'd to UAString
824            Variant::XmlElement(XmlElement::decode(stream, decoding_options)?)
825        } else if Self::test_encoding_flag(encoding_mask, EncodingMask::NODE_ID) {
826            Self::from(NodeId::decode(stream, decoding_options)?)
827        } else if Self::test_encoding_flag(encoding_mask, EncodingMask::EXPANDED_NODE_ID) {
828            Self::from(ExpandedNodeId::decode(stream, decoding_options)?)
829        } else if Self::test_encoding_flag(encoding_mask, EncodingMask::STATUS_CODE) {
830            Self::from(StatusCode::decode(stream, decoding_options)?)
831        } else if Self::test_encoding_flag(encoding_mask, EncodingMask::QUALIFIED_NAME) {
832            Self::from(QualifiedName::decode(stream, decoding_options)?)
833        } else if Self::test_encoding_flag(encoding_mask, EncodingMask::LOCALIZED_TEXT) {
834            Self::from(LocalizedText::decode(stream, decoding_options)?)
835        } else if Self::test_encoding_flag(encoding_mask, EncodingMask::EXTENSION_OBJECT) {
836            // Extension object internally does depth checking to prevent deep recursion
837            Self::from(ExtensionObject::decode(stream, decoding_options)?)
838        } else if Self::test_encoding_flag(encoding_mask, EncodingMask::VARIANT) {
839            // Nested variant is depth checked to prevent deep recursion
840            let _depth_lock = decoding_options.depth_lock()?;
841            Variant::Variant(Box::new(Variant::decode(stream, decoding_options)?))
842        } else if Self::test_encoding_flag(encoding_mask, EncodingMask::DATA_VALUE) {
843            Self::from(DataValue::decode(stream, decoding_options)?)
844        } else if Self::test_encoding_flag(encoding_mask, EncodingMask::DIAGNOSTIC_INFO) {
845            Self::from(DiagnosticInfo::decode(stream, decoding_options)?)
846        } else {
847            Variant::Empty
848        };
849        Ok(result)
850    }
851
852    /// Performs an EXPLICIT cast from one type to another. This will first attempt an implicit
853    /// conversion and only then attempt to cast. Casting is potentially lossy.
854    pub fn cast(&self, target_type: VariantTypeId) -> Variant {
855        let result = self.convert(target_type);
856        if result == Variant::Empty {
857            match *self {
858                Variant::Boolean(v) => match target_type {
859                    VariantTypeId::Byte => Variant::Byte(u8::from(v)),
860                    VariantTypeId::SByte => Variant::SByte(i8::from(v)),
861                    VariantTypeId::Float => Variant::Float(f32::from(v)),
862                    VariantTypeId::Int16 => Variant::Int16(i16::from(v)),
863                    VariantTypeId::Int32 => Variant::Int32(i32::from(v)),
864                    VariantTypeId::Int64 => Variant::Int64(i64::from(v)),
865                    VariantTypeId::UInt16 => Variant::UInt16(u16::from(v)),
866                    VariantTypeId::UInt32 => Variant::UInt32(u32::from(v)),
867                    VariantTypeId::UInt64 => Variant::UInt64(u64::from(v)),
868                    VariantTypeId::Double => Variant::Double(f64::from(v)),
869                    VariantTypeId::String => {
870                        UAString::from(if v { "true" } else { "false" }).into()
871                    }
872                    _ => Variant::Empty,
873                },
874                Variant::Byte(v) => match target_type {
875                    VariantTypeId::Boolean => cast_to_bool!(v),
876                    VariantTypeId::String => format!("{}", v).into(),
877                    _ => Variant::Empty,
878                },
879                Variant::Double(v) => {
880                    // Truncated value used in integer conversions
881                    let vt = f64::trunc(v + 0.5);
882                    match target_type {
883                        VariantTypeId::Boolean => cast_to_bool!(v as i64),
884                        VariantTypeId::Byte => cast_to_integer!(vt, f64, u8),
885                        VariantTypeId::Float => (v as f32).into(),
886                        VariantTypeId::Int16 => cast_to_integer!(vt, f64, i16),
887                        VariantTypeId::Int32 => cast_to_integer!(vt, f64, i32),
888                        VariantTypeId::Int64 => cast_to_integer!(vt, f64, i64),
889                        VariantTypeId::SByte => cast_to_integer!(vt, f64, i8),
890                        VariantTypeId::String => format!("{}", v).into(),
891                        VariantTypeId::UInt16 => cast_to_integer!(vt, f64, u16),
892                        VariantTypeId::UInt32 => cast_to_integer!(vt, f64, u32),
893                        VariantTypeId::UInt64 => cast_to_integer!(vt, f64, u64),
894                        _ => Variant::Empty,
895                    }
896                }
897                Variant::ByteString(ref v) => match target_type {
898                    VariantTypeId::Guid => Guid::try_from(v)
899                        .map(|v| v.into())
900                        .unwrap_or(Variant::Empty),
901                    _ => Variant::Empty,
902                },
903                Variant::DateTime(ref v) => match target_type {
904                    VariantTypeId::String => format!("{}", *v).into(),
905                    _ => Variant::Empty,
906                },
907                Variant::ExpandedNodeId(ref v) => match target_type {
908                    VariantTypeId::NodeId => v.node_id.clone().into(),
909                    _ => Variant::Empty,
910                },
911                Variant::Float(v) => {
912                    let vt = f32::trunc(v + 0.5);
913                    match target_type {
914                        VariantTypeId::Boolean => cast_to_bool!(v as i64),
915                        VariantTypeId::Byte => cast_to_integer!(vt, f32, u8),
916                        VariantTypeId::Int16 => cast_to_integer!(vt, f32, i16),
917                        VariantTypeId::Int32 => cast_to_integer!(vt, f32, i32),
918                        VariantTypeId::Int64 => cast_to_integer!(vt, f32, i64),
919                        VariantTypeId::SByte => cast_to_integer!(vt, f32, i8),
920                        VariantTypeId::String => format!("{}", v).into(),
921                        VariantTypeId::UInt16 => cast_to_integer!(vt, f32, u16),
922                        VariantTypeId::UInt32 => cast_to_integer!(vt, f32, u32),
923                        VariantTypeId::UInt64 => cast_to_integer!(vt, f32, u64),
924                        _ => Variant::Empty,
925                    }
926                }
927                Variant::Guid(ref v) => match target_type {
928                    VariantTypeId::String => format!("{}", *v).into(),
929                    VariantTypeId::ByteString => ByteString::from(v.as_ref().clone()).into(),
930                    _ => Variant::Empty,
931                },
932                Variant::Int16(v) => match target_type {
933                    VariantTypeId::Boolean => cast_to_bool!(v),
934                    VariantTypeId::Byte => cast_to_integer!(v, i16, u8),
935                    VariantTypeId::SByte => cast_to_integer!(v, i16, i8),
936                    VariantTypeId::String => format!("{}", v).into(),
937                    VariantTypeId::UInt16 => cast_to_integer!(v, i16, u16),
938                    _ => Variant::Empty,
939                },
940                Variant::Int32(v) => match target_type {
941                    VariantTypeId::Boolean => cast_to_bool!(v),
942                    VariantTypeId::Byte => cast_to_integer!(v, i32, u8),
943                    VariantTypeId::Int16 => cast_to_integer!(v, i32, i16),
944                    VariantTypeId::SByte => cast_to_integer!(v, i32, i8),
945                    VariantTypeId::StatusCode => (StatusCode::from_bits_truncate(v as u32)).into(),
946                    VariantTypeId::String => format!("{}", v).into(),
947                    VariantTypeId::UInt16 => cast_to_integer!(v, i32, u16),
948                    VariantTypeId::UInt32 => cast_to_integer!(v, i32, u32),
949                    _ => Variant::Empty,
950                },
951                Variant::Int64(v) => match target_type {
952                    VariantTypeId::Boolean => cast_to_bool!(v),
953                    VariantTypeId::Byte => cast_to_integer!(v, i64, u8),
954                    VariantTypeId::Int16 => cast_to_integer!(v, i64, i16),
955                    VariantTypeId::Int32 => cast_to_integer!(v, i64, i32),
956                    VariantTypeId::SByte => cast_to_integer!(v, i64, i8),
957                    VariantTypeId::StatusCode => StatusCode::from_bits_truncate(v as u32).into(),
958                    VariantTypeId::String => format!("{}", v).into(),
959                    VariantTypeId::UInt16 => cast_to_integer!(v, i64, u16),
960                    VariantTypeId::UInt32 => cast_to_integer!(v, i64, u32),
961                    VariantTypeId::UInt64 => cast_to_integer!(v, i64, u64),
962                    _ => Variant::Empty,
963                },
964                Variant::SByte(v) => match target_type {
965                    VariantTypeId::Boolean => cast_to_bool!(v),
966                    VariantTypeId::Byte => cast_to_integer!(v, i8, u8),
967                    VariantTypeId::String => format!("{}", v).into(),
968                    _ => Variant::Empty,
969                },
970                Variant::StatusCode(v) => match target_type {
971                    VariantTypeId::UInt16 => (((v.bits() & 0xffff_0000) >> 16) as u16).into(),
972                    _ => Variant::Empty,
973                },
974                Variant::String(ref v) => match target_type {
975                    VariantTypeId::NodeId => {
976                        if v.is_null() {
977                            Variant::Empty
978                        } else {
979                            NodeId::from_str(v.as_ref())
980                                .map(|v| v.into())
981                                .unwrap_or(Variant::Empty)
982                        }
983                    }
984                    VariantTypeId::ExpandedNodeId => {
985                        if v.is_null() {
986                            Variant::Empty
987                        } else {
988                            ExpandedNodeId::from_str(v.as_ref())
989                                .map(|v| v.into())
990                                .unwrap_or(Variant::Empty)
991                        }
992                    }
993                    VariantTypeId::DateTime => {
994                        if v.is_null() {
995                            Variant::Empty
996                        } else {
997                            DateTime::from_str(v.as_ref())
998                                .map(|v| v.into())
999                                .unwrap_or(Variant::Empty)
1000                        }
1001                    }
1002                    VariantTypeId::LocalizedText => {
1003                        if v.is_null() {
1004                            LocalizedText::null().into()
1005                        } else {
1006                            LocalizedText::new("", v.as_ref()).into()
1007                        }
1008                    }
1009                    VariantTypeId::QualifiedName => {
1010                        if v.is_null() {
1011                            QualifiedName::null().into()
1012                        } else {
1013                            QualifiedName::new(0, v.as_ref()).into()
1014                        }
1015                    }
1016                    _ => Variant::Empty,
1017                },
1018                Variant::UInt16(v) => match target_type {
1019                    VariantTypeId::Boolean => cast_to_bool!(v),
1020                    VariantTypeId::Byte => cast_to_integer!(v, u16, u8),
1021                    VariantTypeId::SByte => cast_to_integer!(v, u16, i8),
1022                    VariantTypeId::String => format!("{}", v).into(),
1023                    _ => Variant::Empty,
1024                },
1025                Variant::UInt32(v) => match target_type {
1026                    VariantTypeId::Boolean => cast_to_bool!(v),
1027                    VariantTypeId::Byte => cast_to_integer!(v, u32, u8),
1028                    VariantTypeId::Int16 => cast_to_integer!(v, u32, i16),
1029                    VariantTypeId::SByte => cast_to_integer!(v, u32, i8),
1030                    VariantTypeId::StatusCode => StatusCode::from_bits_truncate(v).into(),
1031                    VariantTypeId::String => format!("{}", v).into(),
1032                    VariantTypeId::UInt16 => cast_to_integer!(v, u32, u16),
1033                    _ => Variant::Empty,
1034                },
1035                Variant::UInt64(v) => match target_type {
1036                    VariantTypeId::Boolean => cast_to_bool!(v),
1037                    VariantTypeId::Byte => cast_to_integer!(v, u64, u8),
1038                    VariantTypeId::Int16 => cast_to_integer!(v, u64, i16),
1039                    VariantTypeId::SByte => cast_to_integer!(v, u64, i8),
1040                    VariantTypeId::StatusCode => {
1041                        StatusCode::from_bits_truncate((v & 0x0000_0000_ffff_ffff) as u32).into()
1042                    }
1043                    VariantTypeId::String => format!("{}", v).into(),
1044                    VariantTypeId::UInt16 => cast_to_integer!(v, u64, u16),
1045                    VariantTypeId::UInt32 => cast_to_integer!(v, u64, u32),
1046                    _ => Variant::Empty,
1047                },
1048
1049                // NodeId, LocalizedText, QualifiedName, XmlElement have no explicit cast
1050                _ => Variant::Empty,
1051            }
1052        } else {
1053            result
1054        }
1055    }
1056
1057    /// Performs an IMPLICIT conversion from one type to another
1058    pub fn convert(&self, target_type: VariantTypeId) -> Variant {
1059        if self.type_id() == target_type {
1060            return self.clone();
1061        }
1062
1063        // See OPC UA Part 4 table 118
1064        match *self {
1065            Variant::Boolean(v) => {
1066                // true == 1, false == 0
1067                match target_type {
1068                    VariantTypeId::Byte => (v as u8).into(),
1069                    VariantTypeId::Double => ((v as u8) as f64).into(),
1070                    VariantTypeId::Float => ((v as u8) as f32).into(),
1071                    VariantTypeId::Int16 => (v as i16).into(),
1072                    VariantTypeId::Int32 => (v as i32).into(),
1073                    VariantTypeId::Int64 => (v as i64).into(),
1074                    VariantTypeId::SByte => (v as i8).into(),
1075                    VariantTypeId::UInt16 => (v as u16).into(),
1076                    VariantTypeId::UInt32 => (v as u32).into(),
1077                    VariantTypeId::UInt64 => (v as u64).into(),
1078                    _ => Variant::Empty,
1079                }
1080            }
1081            Variant::Byte(v) => match target_type {
1082                VariantTypeId::Double => (v as f64).into(),
1083                VariantTypeId::Float => (v as f32).into(),
1084                VariantTypeId::Int16 => (v as i16).into(),
1085                VariantTypeId::Int32 => (v as i32).into(),
1086                VariantTypeId::Int64 => (v as i64).into(),
1087                VariantTypeId::SByte => (v as i8).into(),
1088                VariantTypeId::UInt16 => (v as u16).into(),
1089                VariantTypeId::UInt32 => (v as u32).into(),
1090                VariantTypeId::UInt64 => (v as u64).into(),
1091                _ => Variant::Empty,
1092            },
1093
1094            // ByteString - everything is X or E except to itself
1095            // DateTime - everything is X or E except to itself
1096            // Double - everything is X or E except to itself
1097            Variant::ExpandedNodeId(ref v) => {
1098                // Everything is X or E except to String
1099                match target_type {
1100                    VariantTypeId::String => format!("{}", v).into(),
1101                    _ => Variant::Empty,
1102                }
1103            }
1104            Variant::Float(v) => {
1105                // Everything is X or E except to Double
1106                match target_type {
1107                    VariantTypeId::Double => (v as f64).into(),
1108                    _ => Variant::Empty,
1109                }
1110            }
1111
1112            // Guid - everything is X or E except to itself
1113            Variant::Int16(v) => match target_type {
1114                VariantTypeId::Double => (v as f64).into(),
1115                VariantTypeId::Float => (v as f32).into(),
1116                VariantTypeId::Int32 => (v as i32).into(),
1117                VariantTypeId::Int64 => (v as i64).into(),
1118                VariantTypeId::UInt32 => {
1119                    if v < 0 {
1120                        Variant::Empty
1121                    } else {
1122                        (v as u32).into()
1123                    }
1124                }
1125                VariantTypeId::UInt64 => {
1126                    if v < 0 {
1127                        Variant::Empty
1128                    } else {
1129                        (v as u64).into()
1130                    }
1131                }
1132                _ => Variant::Empty,
1133            },
1134            Variant::Int32(v) => match target_type {
1135                VariantTypeId::Double => (v as f64).into(),
1136                VariantTypeId::Float => (v as f32).into(),
1137                VariantTypeId::Int64 => (v as i64).into(),
1138                VariantTypeId::UInt64 => {
1139                    if v < 0 {
1140                        Variant::Empty
1141                    } else {
1142                        (v as u64).into()
1143                    }
1144                }
1145                _ => Variant::Empty,
1146            },
1147            Variant::Int64(v) => match target_type {
1148                VariantTypeId::Double => (v as f64).into(),
1149                VariantTypeId::Float => (v as f32).into(),
1150                _ => Variant::Empty,
1151            },
1152            Variant::NodeId(ref v) => {
1153                // Guid - everything is X or E except to ExpandedNodeId and String
1154                match target_type {
1155                    VariantTypeId::ExpandedNodeId => ExpandedNodeId::from(*v.clone()).into(),
1156                    VariantTypeId::String => format!("{}", v).into(),
1157                    _ => Variant::Empty,
1158                }
1159            }
1160            Variant::SByte(v) => match target_type {
1161                VariantTypeId::Double => (v as f64).into(),
1162                VariantTypeId::Float => (v as f32).into(),
1163                VariantTypeId::Int16 => (v as i16).into(),
1164                VariantTypeId::Int32 => (v as i32).into(),
1165                VariantTypeId::Int64 => (v as i64).into(),
1166                VariantTypeId::UInt16 => {
1167                    if v < 0 {
1168                        Variant::Empty
1169                    } else {
1170                        (v as u16).into()
1171                    }
1172                }
1173                VariantTypeId::UInt32 => {
1174                    if v < 0 {
1175                        Variant::Empty
1176                    } else {
1177                        (v as u32).into()
1178                    }
1179                }
1180                VariantTypeId::UInt64 => {
1181                    if v < 0 {
1182                        Variant::Empty
1183                    } else {
1184                        (v as u64).into()
1185                    }
1186                }
1187                _ => Variant::Empty,
1188            },
1189            Variant::StatusCode(v) => match target_type {
1190                VariantTypeId::Int32 => (v.bits() as i32).into(),
1191                VariantTypeId::Int64 => (v.bits() as i64).into(),
1192                VariantTypeId::UInt32 => (v.bits() as u32).into(),
1193                VariantTypeId::UInt64 => (v.bits() as u64).into(),
1194                _ => Variant::Empty,
1195            },
1196            Variant::String(ref v) => {
1197                if v.is_empty() {
1198                    Variant::Empty
1199                } else {
1200                    let v = v.as_ref();
1201                    match target_type {
1202                        VariantTypeId::Boolean => {
1203                            // String values containing “true”, “false”, “1” or “0” can be converted
1204                            // to Boolean values. Other string values cause a conversion error. In
1205                            // this case Strings are case-insensitive.
1206                            if v == "true" || v == "1" {
1207                                true.into()
1208                            } else if v == "false" || v == "0" {
1209                                false.into()
1210                            } else {
1211                                Variant::Empty
1212                            }
1213                        }
1214                        VariantTypeId::Byte => {
1215                            u8::from_str(v).map(|v| v.into()).unwrap_or(Variant::Empty)
1216                        }
1217                        VariantTypeId::Double => {
1218                            f64::from_str(v).map(|v| v.into()).unwrap_or(Variant::Empty)
1219                        }
1220                        VariantTypeId::Float => {
1221                            f32::from_str(v).map(|v| v.into()).unwrap_or(Variant::Empty)
1222                        }
1223                        VariantTypeId::Guid => Guid::from_str(v)
1224                            .map(|v| v.into())
1225                            .unwrap_or(Variant::Empty),
1226                        VariantTypeId::Int16 => {
1227                            i16::from_str(v).map(|v| v.into()).unwrap_or(Variant::Empty)
1228                        }
1229                        VariantTypeId::Int32 => {
1230                            i32::from_str(v).map(|v| v.into()).unwrap_or(Variant::Empty)
1231                        }
1232                        VariantTypeId::Int64 => {
1233                            i64::from_str(v).map(|v| v.into()).unwrap_or(Variant::Empty)
1234                        }
1235                        VariantTypeId::NodeId => NodeId::from_str(v)
1236                            .map(|v| v.into())
1237                            .unwrap_or(Variant::Empty),
1238                        VariantTypeId::SByte => {
1239                            i8::from_str(v).map(|v| v.into()).unwrap_or(Variant::Empty)
1240                        }
1241                        VariantTypeId::UInt16 => {
1242                            u16::from_str(v).map(|v| v.into()).unwrap_or(Variant::Empty)
1243                        }
1244                        VariantTypeId::UInt32 => {
1245                            u32::from_str(v).map(|v| v.into()).unwrap_or(Variant::Empty)
1246                        }
1247                        VariantTypeId::UInt64 => {
1248                            u64::from_str(v).map(|v| v.into()).unwrap_or(Variant::Empty)
1249                        }
1250                        _ => Variant::Empty,
1251                    }
1252                }
1253            }
1254            Variant::LocalizedText(ref v) => match target_type {
1255                VariantTypeId::String => v.text.clone().into(),
1256                _ => Variant::Empty,
1257            },
1258            Variant::QualifiedName(ref v) => {
1259                match target_type {
1260                    VariantTypeId::String => {
1261                        if v.is_null() {
1262                            UAString::null().into()
1263                        } else {
1264                            // drop the namespace index
1265                            v.name.clone().into()
1266                        }
1267                    }
1268                    VariantTypeId::LocalizedText => {
1269                        if v.is_null() {
1270                            LocalizedText::null().into()
1271                        } else {
1272                            // empty locale, drop namespace index
1273                            LocalizedText::new("", v.name.as_ref()).into()
1274                        }
1275                    }
1276                    _ => Variant::Empty,
1277                }
1278            }
1279            Variant::UInt16(v) => {
1280                match target_type {
1281                    VariantTypeId::Double => (v as f64).into(),
1282                    VariantTypeId::Float => (v as f32).into(),
1283                    VariantTypeId::Int16 => (v as i16).into(),
1284                    VariantTypeId::Int32 => (v as i32).into(),
1285                    VariantTypeId::Int64 => (v as i64).into(),
1286                    VariantTypeId::StatusCode => {
1287                        // The 16-bit value is treated as the top 16 bits of the status code
1288                        StatusCode::from_bits_truncate((v as u32) << 16).into()
1289                    }
1290                    VariantTypeId::UInt32 => (v as u32).into(),
1291                    VariantTypeId::UInt64 => (v as u64).into(),
1292                    _ => Variant::Empty,
1293                }
1294            }
1295            Variant::UInt32(v) => match target_type {
1296                VariantTypeId::Double => (v as f64).into(),
1297                VariantTypeId::Float => (v as f32).into(),
1298                VariantTypeId::Int32 => (v as i32).into(),
1299                VariantTypeId::Int64 => (v as i64).into(),
1300                VariantTypeId::UInt64 => (v as u64).into(),
1301                _ => Variant::Empty,
1302            },
1303            Variant::UInt64(v) => match target_type {
1304                VariantTypeId::Double => (v as f64).into(),
1305                VariantTypeId::Float => (v as f32).into(),
1306                VariantTypeId::Int64 => (v as i64).into(),
1307                _ => Variant::Empty,
1308            },
1309            Variant::Array(_) => {
1310                // TODO Arrays including converting array of length 1 to scalar of same type
1311                Variant::Empty
1312            }
1313            // XmlElement everything is X
1314            _ => Variant::Empty,
1315        }
1316    }
1317
1318    pub fn type_id(&self) -> VariantTypeId {
1319        match self {
1320            Variant::Empty => VariantTypeId::Empty,
1321            Variant::Boolean(_) => VariantTypeId::Boolean,
1322            Variant::SByte(_) => VariantTypeId::SByte,
1323            Variant::Byte(_) => VariantTypeId::Byte,
1324            Variant::Int16(_) => VariantTypeId::Int16,
1325            Variant::UInt16(_) => VariantTypeId::UInt16,
1326            Variant::Int32(_) => VariantTypeId::Int32,
1327            Variant::UInt32(_) => VariantTypeId::UInt32,
1328            Variant::Int64(_) => VariantTypeId::Int64,
1329            Variant::UInt64(_) => VariantTypeId::UInt64,
1330            Variant::Float(_) => VariantTypeId::Float,
1331            Variant::Double(_) => VariantTypeId::Double,
1332            Variant::String(_) => VariantTypeId::String,
1333            Variant::DateTime(_) => VariantTypeId::DateTime,
1334            Variant::Guid(_) => VariantTypeId::Guid,
1335            Variant::ByteString(_) => VariantTypeId::ByteString,
1336            Variant::XmlElement(_) => VariantTypeId::XmlElement,
1337            Variant::NodeId(_) => VariantTypeId::NodeId,
1338            Variant::ExpandedNodeId(_) => VariantTypeId::ExpandedNodeId,
1339            Variant::StatusCode(_) => VariantTypeId::StatusCode,
1340            Variant::QualifiedName(_) => VariantTypeId::QualifiedName,
1341            Variant::LocalizedText(_) => VariantTypeId::LocalizedText,
1342            Variant::ExtensionObject(_) => VariantTypeId::ExtensionObject,
1343            Variant::Variant(_) => VariantTypeId::Variant,
1344            Variant::DataValue(_) => VariantTypeId::DataValue,
1345            Variant::DiagnosticInfo(_) => VariantTypeId::DiagnosticInfo,
1346            Variant::Array(_) => VariantTypeId::Array,
1347        }
1348    }
1349
1350    /// Tests and returns true if the variant holds a numeric type
1351    pub fn is_numeric(&self) -> bool {
1352        matches!(
1353            self,
1354            Variant::SByte(_)
1355                | Variant::Byte(_)
1356                | Variant::Int16(_)
1357                | Variant::UInt16(_)
1358                | Variant::Int32(_)
1359                | Variant::UInt32(_)
1360                | Variant::Int64(_)
1361                | Variant::UInt64(_)
1362                | Variant::Float(_)
1363                | Variant::Double(_)
1364        )
1365    }
1366
1367    /// Test if the variant holds an array
1368    pub fn is_array(&self) -> bool {
1369        matches!(self, Variant::Array(_))
1370    }
1371
1372    pub fn is_array_of_type(&self, variant_type: VariantTypeId) -> bool {
1373        // A non-numeric value in the array means it is not numeric
1374        match self {
1375            Variant::Array(array) => values_are_of_type(array.values.as_slice(), variant_type),
1376            _ => false,
1377        }
1378    }
1379
1380    /// Tests that the variant is in a valid state. In particular for arrays ensuring that the
1381    /// values are all acceptable and for a multi dimensional array that the dimensions equal
1382    /// the actual values.
1383    pub fn is_valid(&self) -> bool {
1384        match self {
1385            Variant::Array(array) => array.is_valid(),
1386            _ => true,
1387        }
1388    }
1389
1390    /// Converts the numeric type to a double or returns None
1391    pub fn as_f64(&self) -> Option<f64> {
1392        match *self {
1393            Variant::SByte(value) => Some(value as f64),
1394            Variant::Byte(value) => Some(value as f64),
1395            Variant::Int16(value) => Some(value as f64),
1396            Variant::UInt16(value) => Some(value as f64),
1397            Variant::Int32(value) => Some(value as f64),
1398            Variant::UInt32(value) => Some(value as f64),
1399            Variant::Int64(value) => {
1400                // NOTE: Int64 could overflow
1401                Some(value as f64)
1402            }
1403            Variant::UInt64(value) => {
1404                // NOTE: UInt64 could overflow
1405                Some(value as f64)
1406            }
1407            Variant::Float(value) => Some(value as f64),
1408            Variant::Double(value) => Some(value),
1409            _ => None,
1410        }
1411    }
1412
1413    // Returns the data type of elements in array. Returns None if this is not an array or type
1414    // cannot be determined
1415    pub fn array_data_type(&self) -> Option<NodeId> {
1416        match self {
1417            Variant::Array(array) => {
1418                if array.values.is_empty() {
1419                    error!("Cannot get the data type of an empty array");
1420                    None
1421                } else {
1422                    array.values[0].scalar_data_type()
1423                }
1424            }
1425            _ => None,
1426        }
1427    }
1428
1429    // Returns the scalar data type. Returns None for arrays
1430    pub fn scalar_data_type(&self) -> Option<NodeId> {
1431        match self {
1432            Variant::Boolean(_) => Some(DataTypeId::Boolean.into()),
1433            Variant::SByte(_) => Some(DataTypeId::SByte.into()),
1434            Variant::Byte(_) => Some(DataTypeId::Byte.into()),
1435            Variant::Int16(_) => Some(DataTypeId::Int16.into()),
1436            Variant::UInt16(_) => Some(DataTypeId::UInt16.into()),
1437            Variant::Int32(_) => Some(DataTypeId::Int32.into()),
1438            Variant::UInt32(_) => Some(DataTypeId::UInt32.into()),
1439            Variant::Int64(_) => Some(DataTypeId::Int64.into()),
1440            Variant::UInt64(_) => Some(DataTypeId::UInt64.into()),
1441            Variant::Float(_) => Some(DataTypeId::Float.into()),
1442            Variant::Double(_) => Some(DataTypeId::Double.into()),
1443            Variant::String(_) => Some(DataTypeId::String.into()),
1444            Variant::DateTime(_) => Some(DataTypeId::DateTime.into()),
1445            Variant::Guid(_) => Some(DataTypeId::Guid.into()),
1446            Variant::ByteString(_) => Some(DataTypeId::ByteString.into()),
1447            Variant::XmlElement(_) => Some(DataTypeId::XmlElement.into()),
1448            Variant::NodeId(_) => Some(DataTypeId::NodeId.into()),
1449            Variant::ExpandedNodeId(_) => Some(DataTypeId::ExpandedNodeId.into()),
1450            Variant::StatusCode(_) => Some(DataTypeId::StatusCode.into()),
1451            Variant::QualifiedName(_) => Some(DataTypeId::QualifiedName.into()),
1452            Variant::LocalizedText(_) => Some(DataTypeId::LocalizedText.into()),
1453            Variant::Variant(_) => Some(DataTypeId::BaseDataType.into()),
1454            Variant::DataValue(_) => Some(DataTypeId::DataValue.into()),
1455            Variant::DiagnosticInfo(_) => Some(DataTypeId::DiagnosticInfo.into()),
1456            _ => None,
1457        }
1458    }
1459
1460    // Gets the encoding mask to write the variant to disk
1461    pub(crate) fn encoding_mask(&self) -> u8 {
1462        match self {
1463            Variant::Empty => 0,
1464            Variant::Boolean(_) => EncodingMask::BOOLEAN,
1465            Variant::SByte(_) => EncodingMask::SBYTE,
1466            Variant::Byte(_) => EncodingMask::BYTE,
1467            Variant::Int16(_) => EncodingMask::INT16,
1468            Variant::UInt16(_) => EncodingMask::UINT16,
1469            Variant::Int32(_) => EncodingMask::INT32,
1470            Variant::UInt32(_) => EncodingMask::UINT32,
1471            Variant::Int64(_) => EncodingMask::INT64,
1472            Variant::UInt64(_) => EncodingMask::UINT64,
1473            Variant::Float(_) => EncodingMask::FLOAT,
1474            Variant::Double(_) => EncodingMask::DOUBLE,
1475            Variant::String(_) => EncodingMask::STRING,
1476            Variant::DateTime(_) => EncodingMask::DATE_TIME,
1477            Variant::Guid(_) => EncodingMask::GUID,
1478            Variant::ByteString(_) => EncodingMask::BYTE_STRING,
1479            Variant::XmlElement(_) => EncodingMask::XML_ELEMENT,
1480            Variant::NodeId(_) => EncodingMask::NODE_ID,
1481            Variant::ExpandedNodeId(_) => EncodingMask::EXPANDED_NODE_ID,
1482            Variant::StatusCode(_) => EncodingMask::STATUS_CODE,
1483            Variant::QualifiedName(_) => EncodingMask::QUALIFIED_NAME,
1484            Variant::LocalizedText(_) => EncodingMask::LOCALIZED_TEXT,
1485            Variant::ExtensionObject(_) => EncodingMask::EXTENSION_OBJECT,
1486            Variant::Variant(_) => EncodingMask::VARIANT,
1487            Variant::DataValue(_) => EncodingMask::DATA_VALUE,
1488            Variant::DiagnosticInfo(_) => EncodingMask::DIAGNOSTIC_INFO,
1489            Variant::Array(array) => array.encoding_mask(),
1490        }
1491    }
1492
1493    /// This function is for a special edge case of converting a byte string to a
1494    /// single array of bytes
1495    pub fn to_byte_array(&self) -> Result<Self, StatusCode> {
1496        let array = match self {
1497            Variant::ByteString(values) => match &values.value {
1498                None => Array::new(VariantTypeId::Byte, vec![])?,
1499                Some(values) => {
1500                    let values: Vec<Variant> = values.iter().map(|v| Variant::Byte(*v)).collect();
1501                    Array::new(VariantTypeId::Byte, values)?
1502                }
1503            },
1504            _ => panic!(),
1505        };
1506        Ok(Variant::from(array))
1507    }
1508
1509    /// This function returns a substring of a ByteString or a UAString
1510    fn substring(&self, min: usize, max: usize) -> Result<Variant, StatusCode> {
1511        match self {
1512            Variant::ByteString(v) => v
1513                .substring(min, max)
1514                .map(Variant::from)
1515                .map_err(|_| StatusCode::BadIndexRangeNoData),
1516            Variant::String(v) => v
1517                .substring(min, max)
1518                .map(Variant::from)
1519                .map_err(|_| StatusCode::BadIndexRangeNoData),
1520            _ => panic!("Should not be calling substring on other types"),
1521        }
1522    }
1523
1524    pub fn eq_scalar_type(&self, other: &Variant) -> bool {
1525        let self_data_type = self.scalar_data_type();
1526        let other_data_type = other.scalar_data_type();
1527        if self_data_type.is_none() || other_data_type.is_none() {
1528            false
1529        } else {
1530            self_data_type == other_data_type
1531        }
1532    }
1533
1534    pub fn eq_array_type(&self, other: &Variant) -> bool {
1535        // array
1536        let self_data_type = self.array_data_type();
1537        let other_data_type = other.array_data_type();
1538        if self_data_type.is_none() || other_data_type.is_none() {
1539            false
1540        } else {
1541            self_data_type == other_data_type
1542        }
1543    }
1544
1545    pub fn set_range_of(&mut self, range: NumericRange, other: &Variant) -> Result<(), StatusCode> {
1546        // Types need to be the same
1547        if !self.eq_array_type(other) {
1548            return Err(StatusCode::BadIndexRangeNoData);
1549        }
1550
1551        let other_array = if let Variant::Array(other) = other {
1552            other
1553        } else {
1554            return Err(StatusCode::BadIndexRangeNoData);
1555        };
1556        let other_values = &other_array.values;
1557
1558        // Check value is same type as our array
1559        match self {
1560            Variant::Array(ref mut array) => {
1561                let values = &mut array.values;
1562                match range {
1563                    NumericRange::None => Err(StatusCode::BadIndexRangeNoData),
1564                    NumericRange::Index(idx) => {
1565                        let idx = idx as usize;
1566                        if idx >= values.len() || other_values.is_empty() {
1567                            Err(StatusCode::BadIndexRangeNoData)
1568                        } else {
1569                            values[idx] = other_values[0].clone();
1570                            Ok(())
1571                        }
1572                    }
1573                    NumericRange::Range(min, max) => {
1574                        let (min, max) = (min as usize, max as usize);
1575                        if min >= values.len() {
1576                            Err(StatusCode::BadIndexRangeNoData)
1577                        } else {
1578                            // Possibly this could splice or something but it's trying to copy elements
1579                            // until either the source or destination array is finished.
1580                            let mut idx = min;
1581                            while idx < values.len() && idx <= max && idx - min < other_values.len()
1582                            {
1583                                values[idx] = other_values[idx - min].clone();
1584                                idx += 1;
1585                            }
1586                            Ok(())
1587                        }
1588                    }
1589                    NumericRange::MultipleRanges(_ranges) => {
1590                        // Not yet supported
1591                        error!("Multiple ranges not supported");
1592                        Err(StatusCode::BadIndexRangeNoData)
1593                    }
1594                }
1595            }
1596            _ => {
1597                error!("Writing a range is not supported when the recipient is not an array");
1598                Err(StatusCode::BadWriteNotSupported)
1599            }
1600        }
1601    }
1602
1603    /// This function gets a range of values from the variant if it is an array, or returns a clone
1604    /// of the variant itself.
1605    pub fn range_of(&self, range: NumericRange) -> Result<Variant, StatusCode> {
1606        match range {
1607            NumericRange::None => Ok(self.clone()),
1608            NumericRange::Index(idx) => {
1609                let idx = idx as usize;
1610                match self {
1611                    Variant::String(_) | Variant::ByteString(_) => self.substring(idx, idx),
1612                    Variant::Array(array) => {
1613                        // Get value at the index (or not)
1614                        let values = &array.values;
1615                        if let Some(v) = values.get(idx) {
1616                            let values = vec![v.clone()];
1617                            Ok(Variant::from((array.value_type, values)))
1618                        } else {
1619                            Err(StatusCode::BadIndexRangeNoData)
1620                        }
1621                    }
1622                    _ => Err(StatusCode::BadIndexRangeNoData),
1623                }
1624            }
1625            NumericRange::Range(min, max) => {
1626                let (min, max) = (min as usize, max as usize);
1627                match self {
1628                    Variant::String(_) | Variant::ByteString(_) => self.substring(min, max),
1629                    Variant::Array(array) => {
1630                        let values = &array.values;
1631                        if min >= values.len() {
1632                            // Min must be in range
1633                            Err(StatusCode::BadIndexRangeNoData)
1634                        } else {
1635                            let max = if max >= values.len() {
1636                                values.len() - 1
1637                            } else {
1638                                max
1639                            };
1640                            let values = &values[min as usize..=max];
1641                            let values: Vec<Variant> = values.to_vec();
1642                            Ok(Variant::from((array.value_type, values)))
1643                        }
1644                    }
1645                    _ => Err(StatusCode::BadIndexRangeNoData),
1646                }
1647            }
1648            NumericRange::MultipleRanges(_ranges) => {
1649                // Not yet supported
1650                error!("Multiple ranges not supported");
1651                Err(StatusCode::BadIndexRangeNoData)
1652            }
1653        }
1654    }
1655}