Skip to main content

mabi_opcua/types/
variant.rs

1//! OPC UA Variant type implementation.
2//!
3//! Variant is a union type that can hold any OPC UA built-in data type.
4
5use std::fmt;
6
7use chrono::{DateTime, Utc};
8use serde::{Deserialize, Serialize};
9use uuid::Uuid;
10
11use crate::types::NodeId;
12use mabi_core::Value;
13
14/// Data type IDs matching OPC UA specification.
15#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
16#[repr(u8)]
17pub enum DataTypeId {
18    Null = 0,
19    Boolean = 1,
20    SByte = 2,
21    Byte = 3,
22    Int16 = 4,
23    UInt16 = 5,
24    Int32 = 6,
25    UInt32 = 7,
26    Int64 = 8,
27    UInt64 = 9,
28    Float = 10,
29    Double = 11,
30    String = 12,
31    DateTime = 13,
32    Guid = 14,
33    ByteString = 15,
34    XmlElement = 16,
35    NodeId = 17,
36    ExpandedNodeId = 18,
37    StatusCode = 19,
38    QualifiedName = 20,
39    LocalizedText = 21,
40    ExtensionObject = 22,
41    DataValue = 23,
42    Variant = 24,
43    DiagnosticInfo = 25,
44}
45
46impl DataTypeId {
47    /// Get the data type ID from a numeric value.
48    pub fn from_u8(value: u8) -> Option<Self> {
49        match value {
50            0 => Some(Self::Null),
51            1 => Some(Self::Boolean),
52            2 => Some(Self::SByte),
53            3 => Some(Self::Byte),
54            4 => Some(Self::Int16),
55            5 => Some(Self::UInt16),
56            6 => Some(Self::Int32),
57            7 => Some(Self::UInt32),
58            8 => Some(Self::Int64),
59            9 => Some(Self::UInt64),
60            10 => Some(Self::Float),
61            11 => Some(Self::Double),
62            12 => Some(Self::String),
63            13 => Some(Self::DateTime),
64            14 => Some(Self::Guid),
65            15 => Some(Self::ByteString),
66            16 => Some(Self::XmlElement),
67            17 => Some(Self::NodeId),
68            18 => Some(Self::ExpandedNodeId),
69            19 => Some(Self::StatusCode),
70            20 => Some(Self::QualifiedName),
71            21 => Some(Self::LocalizedText),
72            22 => Some(Self::ExtensionObject),
73            23 => Some(Self::DataValue),
74            24 => Some(Self::Variant),
75            25 => Some(Self::DiagnosticInfo),
76            _ => None,
77        }
78    }
79}
80
81/// Scalar variant values.
82#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
83pub enum VariantScalarValue {
84    /// Null/empty value.
85    Null,
86    /// Boolean.
87    Boolean(bool),
88    /// Signed byte (-128 to 127).
89    SByte(i8),
90    /// Unsigned byte (0 to 255).
91    Byte(u8),
92    /// Signed 16-bit integer.
93    Int16(i16),
94    /// Unsigned 16-bit integer.
95    UInt16(u16),
96    /// Signed 32-bit integer.
97    Int32(i32),
98    /// Unsigned 32-bit integer.
99    UInt32(u32),
100    /// Signed 64-bit integer.
101    Int64(i64),
102    /// Unsigned 64-bit integer.
103    UInt64(u64),
104    /// 32-bit floating point.
105    Float(f32),
106    /// 64-bit floating point.
107    Double(f64),
108    /// UTF-8 string.
109    String(String),
110    /// Date and time.
111    DateTime(DateTime<Utc>),
112    /// GUID.
113    Guid(Uuid),
114    /// Byte string (binary data).
115    ByteString(Vec<u8>),
116    /// XML element (stored as string).
117    XmlElement(String),
118    /// Node ID.
119    NodeId(NodeId),
120    /// Status code.
121    StatusCode(u32),
122}
123
124/// Array variant values.
125#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
126pub enum VariantArrayValue {
127    Boolean(Vec<bool>),
128    SByte(Vec<i8>),
129    Byte(Vec<u8>),
130    Int16(Vec<i16>),
131    UInt16(Vec<u16>),
132    Int32(Vec<i32>),
133    UInt32(Vec<u32>),
134    Int64(Vec<i64>),
135    UInt64(Vec<u64>),
136    Float(Vec<f32>),
137    Double(Vec<f64>),
138    String(Vec<String>),
139    DateTime(Vec<DateTime<Utc>>),
140    Guid(Vec<Uuid>),
141    ByteString(Vec<Vec<u8>>),
142    NodeId(Vec<NodeId>),
143    StatusCode(Vec<u32>),
144}
145
146/// OPC UA Variant type.
147///
148/// A variant can hold either a scalar value or an array of values.
149/// It represents the union of all OPC UA built-in data types.
150///
151/// # Examples
152///
153/// ```
154/// use mabi_opcua::types::Variant;
155///
156/// // Create scalar variants
157/// let bool_var = Variant::boolean(true);
158/// let int_var = Variant::int32(42);
159/// let float_var = Variant::double(3.14);
160///
161/// // Create array variants
162/// let int_array = Variant::int32_array(vec![1, 2, 3, 4, 5]);
163/// ```
164#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
165pub enum Variant {
166    // Scalar shortcuts (for backwards compatibility)
167    /// Boolean value.
168    Boolean(bool),
169    /// Signed byte.
170    SByte(i8),
171    /// Unsigned byte.
172    Byte(u8),
173    /// Signed 16-bit integer.
174    Int16(i16),
175    /// Unsigned 16-bit integer.
176    UInt16(u16),
177    /// Signed 32-bit integer.
178    Int32(i32),
179    /// Unsigned 32-bit integer.
180    UInt32(u32),
181    /// Signed 64-bit integer.
182    Int64(i64),
183    /// Unsigned 64-bit integer.
184    UInt64(u64),
185    /// 32-bit floating point.
186    Float(f32),
187    /// 64-bit floating point.
188    Double(f64),
189    /// UTF-8 string.
190    String(String),
191    /// Date and time.
192    DateTime(chrono::DateTime<Utc>),
193    /// GUID.
194    Guid(Uuid),
195    /// Byte string (binary data).
196    ByteString(Vec<u8>),
197    /// Node ID.
198    NodeId(NodeId),
199    /// Status code.
200    StatusCode(u32),
201    /// Null value.
202    Null,
203    /// Scalar value (wrapped).
204    Scalar(VariantScalarValue),
205    /// Array value.
206    Array(VariantArrayValue),
207}
208
209impl Variant {
210    // ==========================================================================
211    // Scalar Constructors
212    // ==========================================================================
213
214    /// Create a null variant.
215    pub fn null() -> Self {
216        Self::Null
217    }
218
219    /// Create a boolean variant.
220    pub fn boolean(value: bool) -> Self {
221        Self::Boolean(value)
222    }
223
224    /// Create a signed byte variant.
225    pub fn sbyte(value: i8) -> Self {
226        Self::SByte(value)
227    }
228
229    /// Create an unsigned byte variant.
230    pub fn byte(value: u8) -> Self {
231        Self::Byte(value)
232    }
233
234    /// Create a signed 16-bit integer variant.
235    pub fn int16(value: i16) -> Self {
236        Self::Int16(value)
237    }
238
239    /// Create an unsigned 16-bit integer variant.
240    pub fn uint16(value: u16) -> Self {
241        Self::UInt16(value)
242    }
243
244    /// Create a signed 32-bit integer variant.
245    pub fn int32(value: i32) -> Self {
246        Self::Int32(value)
247    }
248
249    /// Create an unsigned 32-bit integer variant.
250    pub fn uint32(value: u32) -> Self {
251        Self::UInt32(value)
252    }
253
254    /// Create a signed 64-bit integer variant.
255    pub fn int64(value: i64) -> Self {
256        Self::Int64(value)
257    }
258
259    /// Create an unsigned 64-bit integer variant.
260    pub fn uint64(value: u64) -> Self {
261        Self::UInt64(value)
262    }
263
264    /// Create a 32-bit float variant.
265    pub fn float(value: f32) -> Self {
266        Self::Float(value)
267    }
268
269    /// Create a 64-bit float variant.
270    pub fn double(value: f64) -> Self {
271        Self::Double(value)
272    }
273
274    /// Create a string variant.
275    pub fn string(value: impl Into<String>) -> Self {
276        Self::String(value.into())
277    }
278
279    /// Create a date/time variant.
280    pub fn datetime(value: DateTime<Utc>) -> Self {
281        Self::DateTime(value)
282    }
283
284    /// Create a GUID variant.
285    pub fn guid(value: Uuid) -> Self {
286        Self::Guid(value)
287    }
288
289    /// Create a byte string variant.
290    pub fn byte_string(value: impl Into<Vec<u8>>) -> Self {
291        Self::ByteString(value.into())
292    }
293
294    /// Create a node ID variant.
295    pub fn node_id(value: NodeId) -> Self {
296        Self::NodeId(value)
297    }
298
299    /// Create a status code variant.
300    pub fn status_code(value: u32) -> Self {
301        Self::StatusCode(value)
302    }
303
304    // ==========================================================================
305    // Array Constructors
306    // ==========================================================================
307
308    /// Create a boolean array variant.
309    pub fn boolean_array(values: Vec<bool>) -> Self {
310        Self::Array(VariantArrayValue::Boolean(values))
311    }
312
313    /// Create an int32 array variant.
314    pub fn int32_array(values: Vec<i32>) -> Self {
315        Self::Array(VariantArrayValue::Int32(values))
316    }
317
318    /// Create an int64 array variant.
319    pub fn int64_array(values: Vec<i64>) -> Self {
320        Self::Array(VariantArrayValue::Int64(values))
321    }
322
323    /// Create a uint32 array variant.
324    pub fn uint32_array(values: Vec<u32>) -> Self {
325        Self::Array(VariantArrayValue::UInt32(values))
326    }
327
328    /// Create a float array variant.
329    pub fn float_array(values: Vec<f32>) -> Self {
330        Self::Array(VariantArrayValue::Float(values))
331    }
332
333    /// Create a double array variant.
334    pub fn double_array(values: Vec<f64>) -> Self {
335        Self::Array(VariantArrayValue::Double(values))
336    }
337
338    /// Create a string array variant.
339    pub fn string_array(values: Vec<String>) -> Self {
340        Self::Array(VariantArrayValue::String(values))
341    }
342
343    /// Create a byte array variant.
344    pub fn byte_array(values: Vec<u8>) -> Self {
345        Self::Array(VariantArrayValue::Byte(values))
346    }
347
348    // ==========================================================================
349    // Accessors
350    // ==========================================================================
351
352    /// Check if this is a null variant.
353    pub fn is_null(&self) -> bool {
354        matches!(self, Self::Null | Self::Scalar(VariantScalarValue::Null))
355    }
356
357    /// Check if this is a scalar variant.
358    pub fn is_scalar(&self) -> bool {
359        !matches!(self, Self::Array(_))
360    }
361
362    /// Check if this is an array variant.
363    pub fn is_array(&self) -> bool {
364        matches!(self, Self::Array(_))
365    }
366
367    /// Get the data type ID.
368    pub fn data_type_id(&self) -> DataTypeId {
369        match self {
370            // Direct variants
371            Self::Null => DataTypeId::Null,
372            Self::Boolean(_) => DataTypeId::Boolean,
373            Self::SByte(_) => DataTypeId::SByte,
374            Self::Byte(_) => DataTypeId::Byte,
375            Self::Int16(_) => DataTypeId::Int16,
376            Self::UInt16(_) => DataTypeId::UInt16,
377            Self::Int32(_) => DataTypeId::Int32,
378            Self::UInt32(_) => DataTypeId::UInt32,
379            Self::Int64(_) => DataTypeId::Int64,
380            Self::UInt64(_) => DataTypeId::UInt64,
381            Self::Float(_) => DataTypeId::Float,
382            Self::Double(_) => DataTypeId::Double,
383            Self::String(_) => DataTypeId::String,
384            Self::DateTime(_) => DataTypeId::DateTime,
385            Self::Guid(_) => DataTypeId::Guid,
386            Self::ByteString(_) => DataTypeId::ByteString,
387            Self::NodeId(_) => DataTypeId::NodeId,
388            Self::StatusCode(_) => DataTypeId::StatusCode,
389            // Wrapped scalar variants
390            Self::Scalar(s) => match s {
391                VariantScalarValue::Null => DataTypeId::Null,
392                VariantScalarValue::Boolean(_) => DataTypeId::Boolean,
393                VariantScalarValue::SByte(_) => DataTypeId::SByte,
394                VariantScalarValue::Byte(_) => DataTypeId::Byte,
395                VariantScalarValue::Int16(_) => DataTypeId::Int16,
396                VariantScalarValue::UInt16(_) => DataTypeId::UInt16,
397                VariantScalarValue::Int32(_) => DataTypeId::Int32,
398                VariantScalarValue::UInt32(_) => DataTypeId::UInt32,
399                VariantScalarValue::Int64(_) => DataTypeId::Int64,
400                VariantScalarValue::UInt64(_) => DataTypeId::UInt64,
401                VariantScalarValue::Float(_) => DataTypeId::Float,
402                VariantScalarValue::Double(_) => DataTypeId::Double,
403                VariantScalarValue::String(_) => DataTypeId::String,
404                VariantScalarValue::DateTime(_) => DataTypeId::DateTime,
405                VariantScalarValue::Guid(_) => DataTypeId::Guid,
406                VariantScalarValue::ByteString(_) => DataTypeId::ByteString,
407                VariantScalarValue::XmlElement(_) => DataTypeId::XmlElement,
408                VariantScalarValue::NodeId(_) => DataTypeId::NodeId,
409                VariantScalarValue::StatusCode(_) => DataTypeId::StatusCode,
410            },
411            // Array variants
412            Self::Array(a) => match a {
413                VariantArrayValue::Boolean(_) => DataTypeId::Boolean,
414                VariantArrayValue::SByte(_) => DataTypeId::SByte,
415                VariantArrayValue::Byte(_) => DataTypeId::Byte,
416                VariantArrayValue::Int16(_) => DataTypeId::Int16,
417                VariantArrayValue::UInt16(_) => DataTypeId::UInt16,
418                VariantArrayValue::Int32(_) => DataTypeId::Int32,
419                VariantArrayValue::UInt32(_) => DataTypeId::UInt32,
420                VariantArrayValue::Int64(_) => DataTypeId::Int64,
421                VariantArrayValue::UInt64(_) => DataTypeId::UInt64,
422                VariantArrayValue::Float(_) => DataTypeId::Float,
423                VariantArrayValue::Double(_) => DataTypeId::Double,
424                VariantArrayValue::String(_) => DataTypeId::String,
425                VariantArrayValue::DateTime(_) => DataTypeId::DateTime,
426                VariantArrayValue::Guid(_) => DataTypeId::Guid,
427                VariantArrayValue::ByteString(_) => DataTypeId::ByteString,
428                VariantArrayValue::NodeId(_) => DataTypeId::NodeId,
429                VariantArrayValue::StatusCode(_) => DataTypeId::StatusCode,
430            },
431        }
432    }
433
434    /// Get as boolean value.
435    pub fn as_bool(&self) -> Option<bool> {
436        match self {
437            Self::Boolean(v) => Some(*v),
438            Self::Scalar(VariantScalarValue::Boolean(v)) => Some(*v),
439            _ => None,
440        }
441    }
442
443    /// Get as i32 value.
444    pub fn as_i32(&self) -> Option<i32> {
445        match self {
446            Self::Int32(v) => Some(*v),
447            Self::Int16(v) => Some(*v as i32),
448            Self::SByte(v) => Some(*v as i32),
449            Self::Scalar(VariantScalarValue::Int32(v)) => Some(*v),
450            Self::Scalar(VariantScalarValue::Int16(v)) => Some(*v as i32),
451            Self::Scalar(VariantScalarValue::SByte(v)) => Some(*v as i32),
452            _ => None,
453        }
454    }
455
456    /// Get as i64 value.
457    pub fn as_i64(&self) -> Option<i64> {
458        match self {
459            Self::Int64(v) => Some(*v),
460            Self::Int32(v) => Some(*v as i64),
461            Self::Int16(v) => Some(*v as i64),
462            Self::SByte(v) => Some(*v as i64),
463            Self::Scalar(VariantScalarValue::Int64(v)) => Some(*v),
464            Self::Scalar(VariantScalarValue::Int32(v)) => Some(*v as i64),
465            Self::Scalar(VariantScalarValue::Int16(v)) => Some(*v as i64),
466            Self::Scalar(VariantScalarValue::SByte(v)) => Some(*v as i64),
467            _ => None,
468        }
469    }
470
471    /// Get as u32 value.
472    pub fn as_u32(&self) -> Option<u32> {
473        match self {
474            Self::UInt32(v) => Some(*v),
475            Self::UInt16(v) => Some(*v as u32),
476            Self::Byte(v) => Some(*v as u32),
477            Self::Scalar(VariantScalarValue::UInt32(v)) => Some(*v),
478            Self::Scalar(VariantScalarValue::UInt16(v)) => Some(*v as u32),
479            Self::Scalar(VariantScalarValue::Byte(v)) => Some(*v as u32),
480            _ => None,
481        }
482    }
483
484    /// Get as u64 value.
485    pub fn as_u64(&self) -> Option<u64> {
486        match self {
487            Self::UInt64(v) => Some(*v),
488            Self::UInt32(v) => Some(*v as u64),
489            Self::UInt16(v) => Some(*v as u64),
490            Self::Byte(v) => Some(*v as u64),
491            Self::Scalar(VariantScalarValue::UInt64(v)) => Some(*v),
492            Self::Scalar(VariantScalarValue::UInt32(v)) => Some(*v as u64),
493            Self::Scalar(VariantScalarValue::UInt16(v)) => Some(*v as u64),
494            Self::Scalar(VariantScalarValue::Byte(v)) => Some(*v as u64),
495            _ => None,
496        }
497    }
498
499    /// Get as f32 value.
500    pub fn as_f32(&self) -> Option<f32> {
501        match self {
502            Self::Float(v) => Some(*v),
503            Self::Scalar(VariantScalarValue::Float(v)) => Some(*v),
504            _ => None,
505        }
506    }
507
508    /// Get as f64 value.
509    pub fn as_f64(&self) -> Option<f64> {
510        match self {
511            Self::Double(v) => Some(*v),
512            Self::Float(v) => Some(*v as f64),
513            Self::Scalar(VariantScalarValue::Double(v)) => Some(*v),
514            Self::Scalar(VariantScalarValue::Float(v)) => Some(*v as f64),
515            _ => None,
516        }
517    }
518
519    /// Get as string reference.
520    pub fn as_str(&self) -> Option<&str> {
521        match self {
522            Self::String(v) => Some(v),
523            Self::Scalar(VariantScalarValue::String(v)) => Some(v),
524            _ => None,
525        }
526    }
527
528    /// Get as DateTime value.
529    pub fn as_datetime(&self) -> Option<DateTime<Utc>> {
530        match self {
531            Self::DateTime(v) => Some(*v),
532            Self::Scalar(VariantScalarValue::DateTime(v)) => Some(*v),
533            _ => None,
534        }
535    }
536
537    /// Get the array length (0 for scalars).
538    pub fn array_len(&self) -> usize {
539        match self {
540            Self::Array(a) => match a {
541                VariantArrayValue::Boolean(v) => v.len(),
542                VariantArrayValue::SByte(v) => v.len(),
543                VariantArrayValue::Byte(v) => v.len(),
544                VariantArrayValue::Int16(v) => v.len(),
545                VariantArrayValue::UInt16(v) => v.len(),
546                VariantArrayValue::Int32(v) => v.len(),
547                VariantArrayValue::UInt32(v) => v.len(),
548                VariantArrayValue::Int64(v) => v.len(),
549                VariantArrayValue::UInt64(v) => v.len(),
550                VariantArrayValue::Float(v) => v.len(),
551                VariantArrayValue::Double(v) => v.len(),
552                VariantArrayValue::String(v) => v.len(),
553                VariantArrayValue::DateTime(v) => v.len(),
554                VariantArrayValue::Guid(v) => v.len(),
555                VariantArrayValue::ByteString(v) => v.len(),
556                VariantArrayValue::NodeId(v) => v.len(),
557                VariantArrayValue::StatusCode(v) => v.len(),
558            },
559            // All scalar variants (direct and wrapped) have length 0
560            _ => 0,
561        }
562    }
563}
564
565impl Default for Variant {
566    fn default() -> Self {
567        Self::null()
568    }
569}
570
571impl fmt::Display for Variant {
572    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
573        match self {
574            // Direct variants
575            Self::Null => write!(f, "null"),
576            Self::Boolean(v) => write!(f, "{}", v),
577            Self::SByte(v) => write!(f, "{}", v),
578            Self::Byte(v) => write!(f, "{}", v),
579            Self::Int16(v) => write!(f, "{}", v),
580            Self::UInt16(v) => write!(f, "{}", v),
581            Self::Int32(v) => write!(f, "{}", v),
582            Self::UInt32(v) => write!(f, "{}", v),
583            Self::Int64(v) => write!(f, "{}", v),
584            Self::UInt64(v) => write!(f, "{}", v),
585            Self::Float(v) => write!(f, "{}", v),
586            Self::Double(v) => write!(f, "{}", v),
587            Self::String(v) => write!(f, "\"{}\"", v),
588            Self::DateTime(v) => write!(f, "{}", v),
589            Self::Guid(v) => write!(f, "{}", v),
590            Self::ByteString(v) => write!(f, "[{} bytes]", v.len()),
591            Self::NodeId(v) => write!(f, "{}", v),
592            Self::StatusCode(v) => write!(f, "0x{:08X}", v),
593            // Wrapped scalar variants
594            Self::Scalar(s) => match s {
595                VariantScalarValue::Null => write!(f, "null"),
596                VariantScalarValue::Boolean(v) => write!(f, "{}", v),
597                VariantScalarValue::SByte(v) => write!(f, "{}", v),
598                VariantScalarValue::Byte(v) => write!(f, "{}", v),
599                VariantScalarValue::Int16(v) => write!(f, "{}", v),
600                VariantScalarValue::UInt16(v) => write!(f, "{}", v),
601                VariantScalarValue::Int32(v) => write!(f, "{}", v),
602                VariantScalarValue::UInt32(v) => write!(f, "{}", v),
603                VariantScalarValue::Int64(v) => write!(f, "{}", v),
604                VariantScalarValue::UInt64(v) => write!(f, "{}", v),
605                VariantScalarValue::Float(v) => write!(f, "{}", v),
606                VariantScalarValue::Double(v) => write!(f, "{}", v),
607                VariantScalarValue::String(v) => write!(f, "\"{}\"", v),
608                VariantScalarValue::DateTime(v) => write!(f, "{}", v),
609                VariantScalarValue::Guid(v) => write!(f, "{}", v),
610                VariantScalarValue::ByteString(v) => write!(f, "[{} bytes]", v.len()),
611                VariantScalarValue::XmlElement(v) => write!(f, "<xml>{}</xml>", v),
612                VariantScalarValue::NodeId(v) => write!(f, "{}", v),
613                VariantScalarValue::StatusCode(v) => write!(f, "0x{:08X}", v),
614            },
615            // Array variants
616            Self::Array(a) => {
617                let len = self.array_len();
618                let type_name = match a {
619                    VariantArrayValue::Boolean(_) => "Boolean",
620                    VariantArrayValue::SByte(_) => "SByte",
621                    VariantArrayValue::Byte(_) => "Byte",
622                    VariantArrayValue::Int16(_) => "Int16",
623                    VariantArrayValue::UInt16(_) => "UInt16",
624                    VariantArrayValue::Int32(_) => "Int32",
625                    VariantArrayValue::UInt32(_) => "UInt32",
626                    VariantArrayValue::Int64(_) => "Int64",
627                    VariantArrayValue::UInt64(_) => "UInt64",
628                    VariantArrayValue::Float(_) => "Float",
629                    VariantArrayValue::Double(_) => "Double",
630                    VariantArrayValue::String(_) => "String",
631                    VariantArrayValue::DateTime(_) => "DateTime",
632                    VariantArrayValue::Guid(_) => "Guid",
633                    VariantArrayValue::ByteString(_) => "ByteString",
634                    VariantArrayValue::NodeId(_) => "NodeId",
635                    VariantArrayValue::StatusCode(_) => "StatusCode",
636                };
637                write!(f, "{}[{}]", type_name, len)
638            }
639        }
640    }
641}
642
643// ==========================================================================
644// Conversions from/to mabi_core::Value
645// ==========================================================================
646
647impl From<Value> for Variant {
648    fn from(value: Value) -> Self {
649        match value {
650            Value::Bool(v) => Variant::boolean(v),
651            Value::I8(v) => Variant::sbyte(v),
652            Value::I16(v) => Variant::int16(v),
653            Value::I32(v) => Variant::int32(v),
654            Value::I64(v) => Variant::int64(v),
655            Value::U8(v) => Variant::byte(v),
656            Value::U16(v) => Variant::uint16(v),
657            Value::U32(v) => Variant::uint32(v),
658            Value::U64(v) => Variant::uint64(v),
659            Value::F32(v) => Variant::float(v),
660            Value::F64(v) => Variant::double(v),
661            Value::String(v) => Variant::string(v),
662            Value::Bytes(v) => Variant::byte_string(v),
663            Value::Null => Variant::null(),
664            Value::Array(arr) => {
665                // Convert array - try to determine type from first element
666                if arr.is_empty() {
667                    return Variant::null();
668                }
669                // For simplicity, convert to array of f64 (most common numeric type)
670                let doubles: Vec<f64> = arr
671                    .into_iter()
672                    .filter_map(|v| match v {
673                        Value::F64(f) => Some(f),
674                        Value::F32(f) => Some(f as f64),
675                        Value::I32(i) => Some(i as f64),
676                        Value::I64(i) => Some(i as f64),
677                        Value::U32(u) => Some(u as f64),
678                        Value::U64(u) => Some(u as f64),
679                        _ => None,
680                    })
681                    .collect();
682                Variant::double_array(doubles)
683            }
684        }
685    }
686}
687
688impl From<Variant> for Value {
689    fn from(variant: Variant) -> Self {
690        match variant {
691            // Direct variants
692            Variant::Null => Value::Null,
693            Variant::Boolean(v) => Value::Bool(v),
694            Variant::SByte(v) => Value::I8(v),
695            Variant::Byte(v) => Value::U8(v),
696            Variant::Int16(v) => Value::I16(v),
697            Variant::UInt16(v) => Value::U16(v),
698            Variant::Int32(v) => Value::I32(v),
699            Variant::UInt32(v) => Value::U32(v),
700            Variant::Int64(v) => Value::I64(v),
701            Variant::UInt64(v) => Value::U64(v),
702            Variant::Float(v) => Value::F32(v),
703            Variant::Double(v) => Value::F64(v),
704            Variant::String(v) => Value::String(v),
705            Variant::DateTime(v) => Value::String(v.to_rfc3339()),
706            Variant::Guid(v) => Value::String(v.to_string()),
707            Variant::ByteString(v) => Value::Bytes(v),
708            Variant::NodeId(v) => Value::String(v.to_string()),
709            Variant::StatusCode(v) => Value::U32(v),
710            // Wrapped scalar variants
711            Variant::Scalar(s) => match s {
712                VariantScalarValue::Null => Value::Null,
713                VariantScalarValue::Boolean(v) => Value::Bool(v),
714                VariantScalarValue::SByte(v) => Value::I8(v),
715                VariantScalarValue::Byte(v) => Value::U8(v),
716                VariantScalarValue::Int16(v) => Value::I16(v),
717                VariantScalarValue::UInt16(v) => Value::U16(v),
718                VariantScalarValue::Int32(v) => Value::I32(v),
719                VariantScalarValue::UInt32(v) => Value::U32(v),
720                VariantScalarValue::Int64(v) => Value::I64(v),
721                VariantScalarValue::UInt64(v) => Value::U64(v),
722                VariantScalarValue::Float(v) => Value::F32(v),
723                VariantScalarValue::Double(v) => Value::F64(v),
724                VariantScalarValue::String(v) => Value::String(v),
725                VariantScalarValue::DateTime(v) => Value::String(v.to_rfc3339()),
726                VariantScalarValue::Guid(v) => Value::String(v.to_string()),
727                VariantScalarValue::ByteString(v) => Value::Bytes(v),
728                VariantScalarValue::XmlElement(v) => Value::String(v),
729                VariantScalarValue::NodeId(v) => Value::String(v.to_string()),
730                VariantScalarValue::StatusCode(v) => Value::U32(v),
731            },
732            // Array variants
733            Variant::Array(a) => {
734                // For arrays, convert to JSON string representation
735                let json = serde_json::to_string(&a).unwrap_or_default();
736                Value::String(json)
737            }
738        }
739    }
740}
741
742// ==========================================================================
743// Conversions from primitive types
744// ==========================================================================
745
746impl From<bool> for Variant {
747    fn from(v: bool) -> Self {
748        Self::boolean(v)
749    }
750}
751
752impl From<i32> for Variant {
753    fn from(v: i32) -> Self {
754        Self::int32(v)
755    }
756}
757
758impl From<i64> for Variant {
759    fn from(v: i64) -> Self {
760        Self::int64(v)
761    }
762}
763
764impl From<u32> for Variant {
765    fn from(v: u32) -> Self {
766        Self::uint32(v)
767    }
768}
769
770impl From<u64> for Variant {
771    fn from(v: u64) -> Self {
772        Self::uint64(v)
773    }
774}
775
776impl From<f32> for Variant {
777    fn from(v: f32) -> Self {
778        Self::float(v)
779    }
780}
781
782impl From<f64> for Variant {
783    fn from(v: f64) -> Self {
784        Self::double(v)
785    }
786}
787
788impl From<String> for Variant {
789    fn from(v: String) -> Self {
790        Self::string(v)
791    }
792}
793
794impl From<&str> for Variant {
795    fn from(v: &str) -> Self {
796        Self::string(v)
797    }
798}
799
800#[cfg(test)]
801mod tests {
802    use super::*;
803
804    #[test]
805    fn test_scalar_variants() {
806        let v = Variant::boolean(true);
807        assert!(v.is_scalar());
808        assert!(!v.is_array());
809        assert_eq!(v.as_bool(), Some(true));
810
811        let v = Variant::int32(42);
812        assert_eq!(v.as_i32(), Some(42));
813        assert_eq!(v.as_i64(), Some(42));
814
815        let v = Variant::double(3.14);
816        assert_eq!(v.as_f64(), Some(3.14));
817    }
818
819    #[test]
820    fn test_array_variants() {
821        let v = Variant::int32_array(vec![1, 2, 3, 4, 5]);
822        assert!(v.is_array());
823        assert!(!v.is_scalar());
824        assert_eq!(v.array_len(), 5);
825    }
826
827    #[test]
828    fn test_data_type_id() {
829        assert_eq!(Variant::boolean(true).data_type_id(), DataTypeId::Boolean);
830        assert_eq!(Variant::int32(42).data_type_id(), DataTypeId::Int32);
831        assert_eq!(Variant::double(3.14).data_type_id(), DataTypeId::Double);
832        assert_eq!(Variant::string("test").data_type_id(), DataTypeId::String);
833    }
834
835    #[test]
836    fn test_from_core_value() {
837        let core_value = Value::I32(42);
838        let variant: Variant = core_value.into();
839        assert_eq!(variant.as_i32(), Some(42));
840
841        let variant = Variant::double(3.14);
842        let core_value: Value = variant.into();
843        assert_eq!(core_value, Value::F64(3.14));
844    }
845
846    #[test]
847    fn test_variant_display() {
848        assert_eq!(Variant::null().to_string(), "null");
849        assert_eq!(Variant::boolean(true).to_string(), "true");
850        assert_eq!(Variant::int32(42).to_string(), "42");
851        assert_eq!(Variant::string("hello").to_string(), "\"hello\"");
852        assert_eq!(Variant::int32_array(vec![1, 2, 3]).to_string(), "Int32[3]");
853    }
854}