opcua_types/variant/
mod.rs

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