1use 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#[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 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#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
83pub enum VariantScalarValue {
84 Null,
86 Boolean(bool),
88 SByte(i8),
90 Byte(u8),
92 Int16(i16),
94 UInt16(u16),
96 Int32(i32),
98 UInt32(u32),
100 Int64(i64),
102 UInt64(u64),
104 Float(f32),
106 Double(f64),
108 String(String),
110 DateTime(DateTime<Utc>),
112 Guid(Uuid),
114 ByteString(Vec<u8>),
116 XmlElement(String),
118 NodeId(NodeId),
120 StatusCode(u32),
122}
123
124#[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#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
165pub enum Variant {
166 Boolean(bool),
169 SByte(i8),
171 Byte(u8),
173 Int16(i16),
175 UInt16(u16),
177 Int32(i32),
179 UInt32(u32),
181 Int64(i64),
183 UInt64(u64),
185 Float(f32),
187 Double(f64),
189 String(String),
191 DateTime(chrono::DateTime<Utc>),
193 Guid(Uuid),
195 ByteString(Vec<u8>),
197 NodeId(NodeId),
199 StatusCode(u32),
201 Null,
203 Scalar(VariantScalarValue),
205 Array(VariantArrayValue),
207}
208
209impl Variant {
210 pub fn null() -> Self {
216 Self::Null
217 }
218
219 pub fn boolean(value: bool) -> Self {
221 Self::Boolean(value)
222 }
223
224 pub fn sbyte(value: i8) -> Self {
226 Self::SByte(value)
227 }
228
229 pub fn byte(value: u8) -> Self {
231 Self::Byte(value)
232 }
233
234 pub fn int16(value: i16) -> Self {
236 Self::Int16(value)
237 }
238
239 pub fn uint16(value: u16) -> Self {
241 Self::UInt16(value)
242 }
243
244 pub fn int32(value: i32) -> Self {
246 Self::Int32(value)
247 }
248
249 pub fn uint32(value: u32) -> Self {
251 Self::UInt32(value)
252 }
253
254 pub fn int64(value: i64) -> Self {
256 Self::Int64(value)
257 }
258
259 pub fn uint64(value: u64) -> Self {
261 Self::UInt64(value)
262 }
263
264 pub fn float(value: f32) -> Self {
266 Self::Float(value)
267 }
268
269 pub fn double(value: f64) -> Self {
271 Self::Double(value)
272 }
273
274 pub fn string(value: impl Into<String>) -> Self {
276 Self::String(value.into())
277 }
278
279 pub fn datetime(value: DateTime<Utc>) -> Self {
281 Self::DateTime(value)
282 }
283
284 pub fn guid(value: Uuid) -> Self {
286 Self::Guid(value)
287 }
288
289 pub fn byte_string(value: impl Into<Vec<u8>>) -> Self {
291 Self::ByteString(value.into())
292 }
293
294 pub fn node_id(value: NodeId) -> Self {
296 Self::NodeId(value)
297 }
298
299 pub fn status_code(value: u32) -> Self {
301 Self::StatusCode(value)
302 }
303
304 pub fn boolean_array(values: Vec<bool>) -> Self {
310 Self::Array(VariantArrayValue::Boolean(values))
311 }
312
313 pub fn int32_array(values: Vec<i32>) -> Self {
315 Self::Array(VariantArrayValue::Int32(values))
316 }
317
318 pub fn int64_array(values: Vec<i64>) -> Self {
320 Self::Array(VariantArrayValue::Int64(values))
321 }
322
323 pub fn uint32_array(values: Vec<u32>) -> Self {
325 Self::Array(VariantArrayValue::UInt32(values))
326 }
327
328 pub fn float_array(values: Vec<f32>) -> Self {
330 Self::Array(VariantArrayValue::Float(values))
331 }
332
333 pub fn double_array(values: Vec<f64>) -> Self {
335 Self::Array(VariantArrayValue::Double(values))
336 }
337
338 pub fn string_array(values: Vec<String>) -> Self {
340 Self::Array(VariantArrayValue::String(values))
341 }
342
343 pub fn byte_array(values: Vec<u8>) -> Self {
345 Self::Array(VariantArrayValue::Byte(values))
346 }
347
348 pub fn is_null(&self) -> bool {
354 matches!(self, Self::Null | Self::Scalar(VariantScalarValue::Null))
355 }
356
357 pub fn is_scalar(&self) -> bool {
359 !matches!(self, Self::Array(_))
360 }
361
362 pub fn is_array(&self) -> bool {
364 matches!(self, Self::Array(_))
365 }
366
367 pub fn data_type_id(&self) -> DataTypeId {
369 match self {
370 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 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 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 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 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 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 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 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 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 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 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 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 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 _ => 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 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 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 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
643impl 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 if arr.is_empty() {
667 return Variant::null();
668 }
669 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 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 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 Variant::Array(a) => {
734 let json = serde_json::to_string(&a).unwrap_or_default();
736 Value::String(json)
737 }
738 }
739 }
740}
741
742impl 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}