1use derive_more::Display;
6use serde::{Deserialize, Serialize};
7use uuid::Uuid;
8
9use crate::keyvalue::KeyValue;
10
11#[derive(Debug, Clone, Display, Serialize, Deserialize, PartialEq)]
12pub enum Type {
13 #[serde(rename = "unit")]
14 Unit,
15 #[serde(rename = "bool")]
16 Boolean,
17 #[serde(rename = "u8")]
18 U8,
19 #[serde(rename = "u16")]
20 U16,
21 #[serde(rename = "u32")]
22 U32,
23 #[serde(rename = "u64")]
24 U64,
25 #[serde(rename = "i8")]
26 I8,
27 #[serde(rename = "i16")]
28 I16,
29 #[serde(rename = "i32")]
30 I32,
31 #[serde(rename = "i64")]
32 I64,
33 #[serde(rename = "f32")]
34 F32,
35 #[serde(rename = "f64")]
36 F64,
37 #[serde(rename = "str")]
38 String,
39 #[serde(rename = "option")]
40 Option,
41 #[serde(rename = "struct")]
42 Structure,
43 #[serde(rename = "enum")]
44 Enumeration,
45 #[serde(rename = "bools")]
46 ArrayBoolean,
47 #[serde(rename = "u8s")]
48 ArrayU8,
49 #[serde(rename = "u16s")]
50 ArrayU16,
51 #[serde(rename = "u32s")]
52 ArrayU32,
53 #[serde(rename = "u64s")]
54 ArrayU64,
55 #[serde(rename = "i8s")]
56 ArrayI8,
57 #[serde(rename = "i16s")]
58 ArrayI16,
59 #[serde(rename = "i32s")]
60 ArrayI32,
61 #[serde(rename = "i64s")]
62 ArrayI64,
63 #[serde(rename = "f32s")]
64 ArrayF32,
65 #[serde(rename = "f64s")]
66 ArrayF64,
67 #[serde(rename = "strs")]
68 ArrayString,
69 #[serde(rename = "values")]
70 ArrayValue,
71 #[serde(rename = "structs")]
72 ArrayStructure,
73 #[serde(rename = "enums")]
74 ArrayEnumeration,
75 #[serde(rename = "keyvalues")]
76 KeyValue,
77 #[serde(rename = "uuids")]
78 Uuid,
79}
80
81#[derive(Debug, Clone, Display, Serialize, Deserialize, PartialEq)]
84pub enum Value {
85 #[serde(rename = "unit")]
86 #[display("()")]
87 Unit,
88 #[serde(rename = "bool")]
89 Boolean(bool),
90 #[serde(rename = "u8")]
91 #[display("{}u8", _0)]
92 U8(u8),
93 #[serde(rename = "u16")]
94 #[display("{}u16", _0)]
95 U16(u16),
96 #[serde(rename = "u32")]
97 #[display("{}u32", _0)]
98 U32(u32),
99 #[serde(rename = "u64")]
100 #[display("{}u64", _0)]
101 U64(u64),
102 #[serde(rename = "i8")]
103 #[display("{}i8", _0)]
104 I8(i8),
105 #[serde(rename = "i16")]
106 #[display("{}i16", _0)]
107 I16(i16),
108 #[serde(rename = "i32")]
109 #[display("{}i32", _0)]
110 I32(i32),
111 #[serde(rename = "i64")]
112 #[display("{}i64", _0)]
113 I64(i64),
114 #[serde(rename = "f32")]
115 #[display("{}f32", _0)]
116 F32(f32),
117 #[serde(rename = "f64")]
118 #[display("{}f64", _0)]
119 F64(f64),
120 #[serde(rename = "str")]
121 #[display("\"{}\"", _0)]
122 String(String),
123 #[serde(rename = "option")]
124 #[display("[{}]", if let Some(v) = _0.as_ref() { format!("{}", v) } else { "null".to_string() })]
125 Option(Option<Box<Value>>),
126 #[serde(rename = "struct")]
127 Structure(Structure),
128 #[serde(rename = "enum")]
129 Enumeration(Enumeration),
130 #[serde(rename = "bools")]
131 #[display("[{:?}]", _0)]
132 ArrayBoolean(Vec<bool>),
133 #[serde(rename = "u8s")]
134 #[display("u8[{:?}]", _0)]
135 ArrayU8(Vec<u8>),
136 #[serde(rename = "u16s")]
137 #[display("u16[{:?}]", _0)]
138 ArrayU16(Vec<u16>),
139 #[serde(rename = "u32s")]
140 #[display("u32[{:?}]", _0)]
141 ArrayU32(Vec<u32>),
142 #[serde(rename = "u64s")]
143 #[display("u64[{:?}]", _0)]
144 ArrayU64(Vec<u64>),
145 #[serde(rename = "i8s")]
146 #[display("i8[{:?}]", _0)]
147 ArrayI8(Vec<i8>),
148 #[serde(rename = "i16s")]
149 #[display("i16[{:?}]", _0)]
150 ArrayI16(Vec<i16>),
151 #[serde(rename = "i32s")]
152 #[display("i32[{:?}]", _0)]
153 ArrayI32(Vec<i32>),
154 #[serde(rename = "i64s")]
155 #[display("i64[{:?}]", _0)]
156 ArrayI64(Vec<i64>),
157 #[serde(rename = "f32s")]
158 #[display("f32[{:?}]", _0)]
159 ArrayF32(Vec<f32>),
160 #[serde(rename = "f64s")]
161 #[display("f64[{:?}]", _0)]
162 ArrayF64(Vec<f64>),
163 #[serde(rename = "strs")]
164 #[display("[{:?}]", _0)]
165 ArrayString(Vec<String>),
166 #[serde(rename = "values")]
167 #[display("[{:?}]", _0)]
168 ArrayValue(Vec<Value>),
169 #[serde(rename = "structs")]
170 #[display("structs({}, {:?})", id, elements)]
171 ArrayStructure {
172 id: Uuid,
173 elements: Vec<StructureWithoutId>,
174 },
175 #[serde(rename = "enums")]
176 #[display("enums({}, {:?})", id, elements)]
177 ArrayEnumeration {
178 id: Uuid,
179 elements: Vec<EnumerationWithoutId>,
180 },
181 #[serde(rename = "keyvalue")]
182 KeyValue(KeyValue),
183 #[serde(rename = "uuid")]
184 #[display("uuid({})", _0)]
185 Uuid(Uuid),
186}
187
188impl Value {
189 pub fn type_uuid(&self) -> Uuid {
195 use crate::ty;
196 match self {
197 Value::Unit => *ty::UNIT_ID,
198 Value::Boolean(_) => *ty::BOOLEAN_ID,
199 Value::I8(_) => *ty::I8_ID,
200 Value::I16(_) => *ty::I16_ID,
201 Value::I32(_) => *ty::I32_ID,
202 Value::I64(_) => *ty::I64_ID,
203 Value::U8(_) => *ty::U8_ID,
204 Value::U16(_) => *ty::U16_ID,
205 Value::U32(_) => *ty::U32_ID,
206 Value::U64(_) => *ty::U64_ID,
207 Value::F32(_) => *ty::F32_ID,
208 Value::F64(_) => *ty::F64_ID,
209 Value::String(_) => *ty::STRING_ID,
210 Value::Option(_) => *ty::OPTION_ID,
211 Value::Structure(s) => s.id,
212 Value::Enumeration(e) => e.id,
213 Value::ArrayBoolean(_) => *ty::ARRAY_BOOLEAN_ID,
214 Value::ArrayU8(_) => *ty::ARRAY_U8_ID,
215 Value::ArrayU16(_) => *ty::ARRAY_U16_ID,
216 Value::ArrayU32(_) => *ty::ARRAY_U32_ID,
217 Value::ArrayU64(_) => *ty::ARRAY_U64_ID,
218 Value::ArrayI8(_) => *ty::ARRAY_I8_ID,
219 Value::ArrayI16(_) => *ty::ARRAY_I16_ID,
220 Value::ArrayI32(_) => *ty::ARRAY_I32_ID,
221 Value::ArrayI64(_) => *ty::ARRAY_I64_ID,
222 Value::ArrayF32(_) => *ty::ARRAY_F32_ID,
223 Value::ArrayF64(_) => *ty::ARRAY_F64_ID,
224 Value::ArrayString(_) => *ty::ARRAY_STRING_ID,
225 Value::ArrayValue(_) => *ty::ARRAY_VALUE_ID,
226 Value::ArrayStructure { id, .. } => *id,
227 Value::ArrayEnumeration { id, .. } => *id,
228 Value::KeyValue(_) => *ty::KEY_VALUE_ID,
229 Value::Uuid(_) => *ty::UUID_ID,
230 }
231 }
232}
233
234#[derive(Debug, Clone, Display, Serialize, Deserialize, PartialEq)]
235#[display("{}::{}({})", id, variant_id, value)]
236pub struct Enumeration {
237 pub id: Uuid,
238 pub variant_id: Uuid,
239 pub value: Box<Value>,
240}
241
242#[derive(Debug, Clone, Display, Serialize, Deserialize, PartialEq)]
243#[display("{}({:?})", id, fields)]
244pub struct Structure {
245 pub id: Uuid,
246 pub fields: Vec<StructureField>,
247}
248
249#[derive(Debug, Clone, Display, Serialize, Deserialize, PartialEq)]
250#[display("{}: {}", id, value)]
251pub struct StructureField {
252 pub id: Uuid,
253 pub value: Box<Value>,
254}
255
256#[derive(Debug, Clone, Display, Serialize, Deserialize, PartialEq)]
257#[display("({:?})", fields)]
258pub struct StructureWithoutId {
259 pub fields: Vec<StructureField>,
261}
262
263#[derive(Debug, Clone, Display, Serialize, Deserialize, PartialEq)]
264#[display("{}({})", variant_id, value)]
265pub struct EnumerationWithoutId {
266 pub variant_id: Uuid,
267 pub value: Box<Value>,
268}
269
270#[derive(Display, Debug)]
272pub struct ConversionError {
273 pub message: String,
274}
275
276impl std::error::Error for ConversionError {}
277
278impl From<()> for Value {
279 fn from(_: ()) -> Self {
280 Value::Unit
281 }
282}
283
284impl From<bool> for Value {
285 fn from(v: bool) -> Self {
286 Value::Boolean(v)
287 }
288}
289
290impl From<u8> for Value {
291 fn from(v: u8) -> Self {
292 Value::U8(v)
293 }
294}
295
296impl From<u16> for Value {
297 fn from(v: u16) -> Self {
298 Value::U16(v)
299 }
300}
301
302impl From<u32> for Value {
303 fn from(v: u32) -> Self {
304 Value::U32(v)
305 }
306}
307
308impl From<u64> for Value {
309 fn from(v: u64) -> Self {
310 Value::U64(v)
311 }
312}
313
314impl From<i8> for Value {
315 fn from(v: i8) -> Self {
316 Value::I8(v)
317 }
318}
319
320impl From<i16> for Value {
321 fn from(v: i16) -> Self {
322 Value::I16(v)
323 }
324}
325
326impl From<i32> for Value {
327 fn from(v: i32) -> Self {
328 Value::I32(v)
329 }
330}
331
332impl From<i64> for Value {
333 fn from(v: i64) -> Self {
334 Value::I64(v)
335 }
336}
337
338impl From<f32> for Value {
339 fn from(v: f32) -> Self {
340 Value::F32(v)
341 }
342}
343
344impl From<f64> for Value {
345 fn from(v: f64) -> Self {
346 Value::F64(v)
347 }
348}
349
350impl From<String> for Value {
351 fn from(v: String) -> Self {
352 Value::String(v)
353 }
354}
355
356impl From<&str> for Value {
357 fn from(v: &str) -> Self {
358 Value::String(v.to_string())
359 }
360}
361
362impl From<Uuid> for Value {
363 fn from(v: Uuid) -> Self {
364 Value::Uuid(v)
365 }
366}
367
368impl<T> From<Option<T>> for Value
370where
371 T: Into<Value>,
372{
373 fn from(opt: Option<T>) -> Self {
374 match opt {
375 Some(value) => Value::Option(Some(Box::new(value.into()))),
376 None => Value::Option(None),
377 }
378 }
379}
380
381impl From<Vec<Value>> for Value {
383 fn from(vec: Vec<Value>) -> Self {
384 Value::ArrayValue(vec)
385 }
386}
387
388impl From<&[Value]> for Value {
390 fn from(slice: &[Value]) -> Self {
391 Value::ArrayValue(slice.to_vec())
392 }
393}
394
395macro_rules! impl_array_conversions {
397 ($(($rust_type:ty, $variant:ident)),* $(,)?) => {
398 $(
399 impl From<Vec<$rust_type>> for Value {
401 fn from(vec: Vec<$rust_type>) -> Self {
402 Value::$variant(vec)
403 }
404 }
405
406 impl From<&[$rust_type]> for Value {
408 fn from(slice: &[$rust_type]) -> Self {
409 Value::$variant(slice.to_vec())
410 }
411 }
412
413 impl From<std::collections::HashSet<$rust_type>> for Value {
415 fn from(set: std::collections::HashSet<$rust_type>) -> Self {
416 Value::$variant(set.into_iter().collect())
417 }
418 }
419 )*
420 };
421}
422
423impl_array_conversions! {
425 (bool, ArrayBoolean),
426 (u8, ArrayU8),
427 (u16, ArrayU16),
428 (u32, ArrayU32),
429 (u64, ArrayU64),
430 (i8, ArrayI8),
431 (i16, ArrayI16),
432 (i32, ArrayI32),
433 (i64, ArrayI64),
434 (String, ArrayString),
435}
436
437macro_rules! impl_float_array_conversions {
439 ($(($rust_type:ty, $variant:ident)),* $(,)?) => {
440 $(
441 impl From<Vec<$rust_type>> for Value {
443 fn from(vec: Vec<$rust_type>) -> Self {
444 Value::$variant(vec)
445 }
446 }
447
448 impl From<&[$rust_type]> for Value {
450 fn from(slice: &[$rust_type]) -> Self {
451 Value::$variant(slice.to_vec())
452 }
453 }
454 )*
455 };
456}
457
458impl_float_array_conversions! {
460 (f32, ArrayF32),
461 (f64, ArrayF64),
462}
463
464#[cfg(test)]
467mod tests {
468 use super::*;
469 use json5;
470 use pretty_assertions::assert_eq;
471
472 fn test_serde_roundtrip<T>(value: &T, name: &str)
474 where
475 T: Serialize + for<'de> Deserialize<'de> + PartialEq + std::fmt::Debug + Clone,
476 {
477 let json = json5::to_string(value).unwrap();
479 println!("{} JSON:\n{}", name, json);
480
481 let deserialized: T = json5::from_str(&json).unwrap();
482 assert_eq!(
483 value, &deserialized,
484 "Roundtrip JSON serialization failed for {name}"
485 );
486
487 let ron = ron::to_string(value).unwrap();
489 println!("{} RON:\n{}", name, ron);
490 let deserialized: T = ron::from_str(&ron).unwrap();
491 assert_eq!(
492 value, &deserialized,
493 "Roundtrip RON serialization failed for {name}"
494 );
495 }
496
497 #[test]
501 fn value_round_trips_through_yaml() {
502 let value = Value::Structure(Structure {
503 id: Uuid::from_u128(0x10),
504 fields: vec![
505 StructureField {
506 id: Uuid::from_u128(0x01),
507 value: Box::new(Value::ArrayF64(vec![1.0, -2.0, 3.5])),
508 },
509 StructureField {
510 id: Uuid::from_u128(0x02),
511 value: Box::new(Value::String("hi".to_string())),
512 },
513 ],
514 });
515 let yaml = serde_yaml::to_string(&value).unwrap();
516 let back: Value = serde_yaml::from_str(&yaml).unwrap();
517 assert_eq!(value, back, "Value did not round-trip through YAML");
518 }
519
520 #[test]
521 fn test_type_serialization() {
522 for typ in [
524 Type::Unit,
525 Type::Boolean,
526 Type::U8,
527 Type::U16,
528 Type::U32,
529 Type::U64,
530 Type::I8,
531 Type::I16,
532 Type::I32,
533 Type::I64,
534 Type::F32,
535 Type::F64,
536 Type::String,
537 Type::Option,
538 Type::Structure,
539 Type::Enumeration,
540 Type::ArrayBoolean,
541 Type::ArrayU8,
542 Type::ArrayU16,
543 Type::ArrayU32,
544 Type::ArrayU64,
545 Type::ArrayI8,
546 Type::ArrayI16,
547 Type::ArrayI32,
548 Type::ArrayI64,
549 Type::ArrayF32,
550 Type::ArrayF64,
551 Type::ArrayString,
552 Type::ArrayValue,
553 Type::ArrayStructure,
554 Type::ArrayEnumeration,
555 Type::KeyValue,
556 Type::Uuid,
557 ] {
558 test_serde_roundtrip(&typ, &format!("Type::{:?}", typ));
559 }
560 }
561
562 #[test]
563 fn test_value_primitive_serialization() {
564 let primitives = vec![
566 ("Unit", Value::Unit),
567 ("Boolean_true", Value::Boolean(true)),
568 ("Boolean_false", Value::Boolean(false)),
569 ("U8_min", Value::U8(0)),
570 ("U8_max", Value::U8(u8::MAX)),
571 ("U16_max", Value::U16(u16::MAX)),
572 ("U32_max", Value::U32(u32::MAX)),
573 ("U64_max", Value::U64(u64::MAX)),
574 ("I8_min", Value::I8(i8::MIN)),
575 ("I8_max", Value::I8(i8::MAX)),
576 ("I16_min", Value::I16(i16::MIN)),
577 ("I32_min", Value::I32(i32::MIN)),
578 ("I64_min", Value::I64(i64::MIN)),
579 ("F32_zero", Value::F32(0.0)),
580 ("F32_inf", Value::F32(f32::INFINITY)),
581 ("F32_neg_inf", Value::F32(f32::NEG_INFINITY)),
582 ("F64_zero", Value::F64(0.0)),
583 ("F64_inf", Value::F64(f64::INFINITY)),
584 ("F64_neg_inf", Value::F64(f64::NEG_INFINITY)),
585 ("String_empty", Value::String("".to_string())),
586 ("String_hello", Value::String("Hello, world!".to_string())),
587 (
588 "String_special",
589 Value::String("Special chars: \n\t\r\"\\".to_string()),
590 ),
591 ];
592
593 for (name, value) in primitives {
594 test_serde_roundtrip(&value, name);
595 }
596
597 let f32_nan = Value::F32(f32::NAN);
599 let f32_json = json5::to_string(&f32_nan).unwrap();
600 println!("F32_NaN JSON:\n{}", f32_json);
601 let deserialized_f32: Value = json5::from_str(&f32_json).unwrap();
602 if let Value::F32(val) = deserialized_f32 {
603 assert!(val.is_nan(), "Deserialized F32 should be NaN");
604 }
605
606 let f64_nan = Value::F64(f64::NAN);
607 let f64_json = json5::to_string(&f64_nan).unwrap();
608 println!("F64_NaN JSON:\n{}", f64_json);
609 let deserialized_f64: Value = json5::from_str(&f64_json).unwrap();
610 if let Value::F64(val) = deserialized_f64 {
611 assert!(val.is_nan(), "Deserialized F64 should be NaN");
612 }
613 }
614
615 #[test]
616 fn test_value_array_serialization() {
617 let arrays = vec![
619 ("ArrayBoolean_empty", Value::ArrayBoolean(vec![])),
620 ("ArrayBoolean", Value::ArrayBoolean(vec![true, false])),
621 ("ArrayU8", Value::ArrayU8(vec![0, 123, 255])),
622 ("ArrayI32", Value::ArrayI32(vec![i32::MIN, 0, i32::MAX])),
623 (
624 "ArrayF64",
625 Value::ArrayF64(vec![-1.0, 0.0, 1.0, f64::INFINITY]),
626 ),
627 (
628 "ArrayString",
629 Value::ArrayString(vec!["a".to_string(), "b".to_string()]),
630 ),
631 ];
632
633 for (name, value) in arrays {
634 test_serde_roundtrip(&value, name);
635 }
636 }
637
638 #[test]
639 fn test_structure_field_serialization() {
640 let field = StructureField {
641 id: Uuid::parse_str("550e8400-e29b-41d4-a716-446655440000").unwrap(),
642 value: Box::new(Value::String("test field".to_string())),
643 };
644
645 test_serde_roundtrip(&field, "StructureField");
646 }
647
648 #[test]
649 fn test_structure_serialization() {
650 let empty_structure = Structure {
652 id: Uuid::parse_str("550e8400-e29b-41d4-a716-446655440000").unwrap(),
653 fields: vec![],
654 };
655
656 test_serde_roundtrip(&empty_structure, "EmptyStructure");
657
658 let structure = Structure {
660 id: Uuid::parse_str("550e8400-e29b-41d4-a716-446655440000").unwrap(),
661 fields: vec![
662 StructureField {
663 id: Uuid::parse_str("550e8400-e29b-41d4-a716-446655440001").unwrap(),
664 value: Box::new(Value::String("field1".to_string())),
665 },
666 StructureField {
667 id: Uuid::parse_str("550e8400-e29b-41d4-a716-446655440002").unwrap(),
668 value: Box::new(Value::I32(42)),
669 },
670 ],
671 };
672
673 test_serde_roundtrip(&structure, "Structure");
674 }
675
676 #[test]
677 fn test_structure_without_id_serialization() {
678 let structure_without_id = StructureWithoutId {
679 fields: vec![StructureField {
680 id: Uuid::parse_str("550e8400-e29b-41d4-a716-446655440001").unwrap(),
681 value: Box::new(Value::String("field1".to_string())),
682 }],
683 };
684
685 test_serde_roundtrip(&structure_without_id, "StructureWithoutId");
686 }
687
688 #[test]
689 fn test_enumeration_serialization() {
690 let enumeration = Enumeration {
691 id: Uuid::parse_str("550e8400-e29b-41d4-a716-446655440000").unwrap(),
692 variant_id: Uuid::parse_str("550e8400-e29b-41d4-a716-446655440001").unwrap(),
693 value: Box::new(Value::String("variant value".to_string())),
694 };
695
696 test_serde_roundtrip(&enumeration, "Enumeration");
697 }
698
699 #[test]
700 fn test_enumeration_without_id_serialization() {
701 let enumeration_without_id = EnumerationWithoutId {
702 variant_id: Uuid::parse_str("550e8400-e29b-41d4-a716-446655440001").unwrap(),
703 value: Box::new(Value::String("variant value".to_string())),
704 };
705
706 test_serde_roundtrip(&enumeration_without_id, "EnumerationWithoutId");
707 }
708
709 #[test]
710 fn test_complex_nested_values() {
711 let complex_value = Value::Structure(Structure {
713 id: Uuid::parse_str("550e8400-e29b-41d4-a716-446655440000").unwrap(),
714 fields: vec![
715 StructureField {
716 id: Uuid::parse_str("550e8400-e29b-41d4-a716-446655440001").unwrap(),
717 value: Box::new(Value::String("name".to_string())),
718 },
719 StructureField {
720 id: Uuid::parse_str("550e8400-e29b-41d4-a716-446655440002").unwrap(),
721 value: Box::new(Value::Enumeration(Enumeration {
722 id: Uuid::parse_str("550e8400-e29b-41d4-a716-446655440003").unwrap(),
723 variant_id: Uuid::parse_str("550e8400-e29b-41d4-a716-446655440004").unwrap(),
724 value: Box::new(Value::Boolean(true)),
725 })),
726 },
727 ],
728 });
729
730 test_serde_roundtrip(&complex_value, "ComplexNestedValue");
731 }
732
733 #[test]
734 fn test_array_structure_and_enumeration() {
735 let array_structure = Value::ArrayStructure {
737 id: Uuid::parse_str("550e8400-e29b-41d4-a716-446655440000").unwrap(),
738 elements: vec![
739 StructureWithoutId {
740 fields: vec![StructureField {
741 id: Uuid::parse_str("550e8400-e29b-41d4-a716-446655440001").unwrap(),
742 value: Box::new(Value::String("element1".to_string())),
743 }],
744 },
745 StructureWithoutId { fields: vec![] }, ],
747 };
748
749 test_serde_roundtrip(&array_structure, "ArrayStructure");
750
751 let array_enumeration = Value::ArrayEnumeration {
753 id: Uuid::parse_str("550e8400-e29b-41d4-a716-446655440000").unwrap(),
754 elements: vec![
755 EnumerationWithoutId {
756 variant_id: Uuid::parse_str("550e8400-e29b-41d4-a716-446655440001").unwrap(),
757 value: Box::new(Value::String("variant1".to_string())),
758 },
759 EnumerationWithoutId {
760 variant_id: Uuid::parse_str("550e8400-e29b-41d4-a716-446655440002").unwrap(),
761 value: Box::new(Value::U32(42)),
762 },
763 ],
764 };
765
766 test_serde_roundtrip(&array_enumeration, "ArrayEnumeration");
767 }
768
769 #[test]
770 fn test_from_conversions_primitives() {
771 assert_eq!(Value::from(()), Value::Unit);
773 assert_eq!(Value::from(true), Value::Boolean(true));
774 assert_eq!(Value::from(false), Value::Boolean(false));
775
776 assert_eq!(Value::from(42u8), Value::U8(42));
777 assert_eq!(Value::from(1234u16), Value::U16(1234));
778 assert_eq!(Value::from(123456u32), Value::U32(123456));
779 assert_eq!(Value::from(12345678901234u64), Value::U64(12345678901234));
780
781 assert_eq!(Value::from(-42i8), Value::I8(-42));
782 assert_eq!(Value::from(-1234i16), Value::I16(-1234));
783 assert_eq!(Value::from(-123456i32), Value::I32(-123456));
784 assert_eq!(Value::from(-12345678901234i64), Value::I64(-12345678901234));
785
786 assert_eq!(
787 Value::from(std::f32::consts::PI),
788 Value::F32(std::f32::consts::PI)
789 );
790 assert_eq!(
791 Value::from(std::f64::consts::PI),
792 Value::F64(std::f64::consts::PI)
793 );
794
795 assert_eq!(
796 Value::from("hello".to_string()),
797 Value::String("hello".to_string())
798 );
799 assert_eq!(Value::from("world"), Value::String("world".to_string()));
800
801 let uuid = Uuid::parse_str("550e8400-e29b-41d4-a716-446655440000").unwrap();
802 assert_eq!(Value::from(uuid), Value::Uuid(uuid));
803 }
804
805 #[test]
806 fn test_from_conversions_arrays_vec() {
807 assert_eq!(
809 Value::from(vec![true, false, true]),
810 Value::ArrayBoolean(vec![true, false, true])
811 );
812 assert_eq!(
813 Value::from(vec![1u8, 2u8, 3u8]),
814 Value::ArrayU8(vec![1, 2, 3])
815 );
816 assert_eq!(
817 Value::from(vec![100u16, 200u16]),
818 Value::ArrayU16(vec![100, 200])
819 );
820 assert_eq!(
821 Value::from(vec![1000u32, 2000u32]),
822 Value::ArrayU32(vec![1000, 2000])
823 );
824 assert_eq!(
825 Value::from(vec![10000u64, 20000u64]),
826 Value::ArrayU64(vec![10000, 20000])
827 );
828
829 assert_eq!(Value::from(vec![-1i8, -2i8]), Value::ArrayI8(vec![-1, -2]));
830 assert_eq!(
831 Value::from(vec![-100i16, -200i16]),
832 Value::ArrayI16(vec![-100, -200])
833 );
834 assert_eq!(
835 Value::from(vec![-1000i32, -2000i32]),
836 Value::ArrayI32(vec![-1000, -2000])
837 );
838 assert_eq!(
839 Value::from(vec![-10000i64, -20000i64]),
840 Value::ArrayI64(vec![-10000, -20000])
841 );
842
843 assert_eq!(
844 Value::from(vec![1.5f32, 2.5f32]),
845 Value::ArrayF32(vec![1.5, 2.5])
846 );
847 assert_eq!(
848 Value::from(vec![1.5f64, 2.5f64]),
849 Value::ArrayF64(vec![1.5, 2.5])
850 );
851
852 assert_eq!(
853 Value::from(vec!["hello".to_string(), "world".to_string()]),
854 Value::ArrayString(vec!["hello".to_string(), "world".to_string()])
855 );
856 }
857
858 #[test]
859 fn test_from_conversions_arrays_slices() {
860 let bool_slice = &[true, false, true][..];
862 assert_eq!(
863 Value::from(bool_slice),
864 Value::ArrayBoolean(vec![true, false, true])
865 );
866
867 let u32_slice = &[1u32, 2u32, 3u32][..];
868 assert_eq!(Value::from(u32_slice), Value::ArrayU32(vec![1, 2, 3]));
869
870 let string_slice = &["a".to_string(), "b".to_string()][..];
871 assert_eq!(
872 Value::from(string_slice),
873 Value::ArrayString(vec!["a".to_string(), "b".to_string()])
874 );
875 }
876
877 #[test]
878 fn test_from_conversions_hashset() {
879 use std::collections::HashSet;
880
881 let bool_set: HashSet<bool> = [true, false].into_iter().collect();
883 if let Value::ArrayBoolean(vec) = Value::from(bool_set) {
884 assert_eq!(vec.len(), 2);
885 assert!(vec.contains(&true));
886 assert!(vec.contains(&false));
887 } else {
888 panic!("Expected ArrayBoolean");
889 }
890
891 let u32_set: HashSet<u32> = [1, 2, 3].into_iter().collect();
892 if let Value::ArrayU32(vec) = Value::from(u32_set) {
893 assert_eq!(vec.len(), 3);
894 assert!(vec.contains(&1));
895 assert!(vec.contains(&2));
896 assert!(vec.contains(&3));
897 } else {
898 panic!("Expected ArrayU32");
899 }
900
901 let string_set: HashSet<String> = ["a".to_string(), "b".to_string()].into_iter().collect();
902 if let Value::ArrayString(vec) = Value::from(string_set) {
903 assert_eq!(vec.len(), 2);
904 assert!(vec.contains(&"a".to_string()));
905 assert!(vec.contains(&"b".to_string()));
906 } else {
907 panic!("Expected ArrayString");
908 }
909
910 let empty_set: HashSet<u32> = HashSet::new();
912 assert_eq!(Value::from(empty_set), Value::ArrayU32(vec![]));
913 }
914
915 #[test]
916 fn test_from_conversions_empty_arrays() {
917 assert_eq!(Value::from(Vec::<bool>::new()), Value::ArrayBoolean(vec![]));
919 assert_eq!(Value::from(Vec::<u8>::new()), Value::ArrayU8(vec![]));
920 assert_eq!(Value::from(Vec::<u16>::new()), Value::ArrayU16(vec![]));
921 assert_eq!(Value::from(Vec::<u32>::new()), Value::ArrayU32(vec![]));
922 assert_eq!(Value::from(Vec::<u64>::new()), Value::ArrayU64(vec![]));
923 assert_eq!(Value::from(Vec::<i8>::new()), Value::ArrayI8(vec![]));
924 assert_eq!(Value::from(Vec::<i16>::new()), Value::ArrayI16(vec![]));
925 assert_eq!(Value::from(Vec::<i32>::new()), Value::ArrayI32(vec![]));
926 assert_eq!(Value::from(Vec::<i64>::new()), Value::ArrayI64(vec![]));
927 assert_eq!(Value::from(Vec::<f32>::new()), Value::ArrayF32(vec![]));
928 assert_eq!(Value::from(Vec::<f64>::new()), Value::ArrayF64(vec![]));
929 assert_eq!(
930 Value::from(Vec::<String>::new()),
931 Value::ArrayString(vec![])
932 );
933 }
934
935 #[test]
936 fn test_from_conversions_option() {
937 assert_eq!(
941 Value::from(Some(42u32)),
942 Value::Option(Some(Box::new(Value::U32(42))))
943 );
944 assert_eq!(
945 Value::from(Some(true)),
946 Value::Option(Some(Box::new(Value::Boolean(true))))
947 );
948 assert_eq!(
949 Value::from(Some("hello".to_string())),
950 Value::Option(Some(Box::new(Value::String("hello".to_string()))))
951 );
952 assert_eq!(
953 Value::from(Some(std::f64::consts::PI)),
954 Value::Option(Some(Box::new(Value::F64(std::f64::consts::PI))))
955 );
956
957 assert_eq!(Value::from(None::<u32>), Value::Option(None));
959 assert_eq!(Value::from(None::<bool>), Value::Option(None));
960 assert_eq!(Value::from(None::<String>), Value::Option(None));
961 assert_eq!(Value::from(None::<f64>), Value::Option(None));
962
963 let nested_value = Value::ArrayU32(vec![1, 2, 3]);
965 assert_eq!(
966 Value::from(Some(nested_value.clone())),
967 Value::Option(Some(Box::new(nested_value)))
968 );
969 assert_eq!(Value::from(None::<Value>), Value::Option(None));
970 }
971
972 #[test]
973 fn test_from_conversions_array_value() {
974 assert_eq!(Value::from(Vec::<Value>::new()), Value::ArrayValue(vec![]));
978
979 let mixed_values = vec![
981 Value::U32(42),
982 Value::Boolean(true),
983 Value::String("test".to_string()),
984 Value::F64(std::f64::consts::PI),
985 Value::Unit,
986 ];
987 assert_eq!(
988 Value::from(mixed_values.clone()),
989 Value::ArrayValue(mixed_values.clone())
990 );
991
992 let values_slice = &[
994 Value::I32(-10),
995 Value::Boolean(false),
996 Value::String("slice".to_string()),
997 ][..];
998 assert_eq!(
999 Value::from(values_slice),
1000 Value::ArrayValue(vec![
1001 Value::I32(-10),
1002 Value::Boolean(false),
1003 Value::String("slice".to_string()),
1004 ])
1005 );
1006
1007 let nested_array = vec![
1009 Value::ArrayU32(vec![1, 2, 3]),
1010 Value::ArrayString(vec!["a".to_string(), "b".to_string()]),
1011 Value::ArrayBoolean(vec![true, false]),
1012 ];
1013 assert_eq!(
1014 Value::from(nested_array.clone()),
1015 Value::ArrayValue(nested_array)
1016 );
1017
1018 let option_array = vec![
1020 Value::Option(Some(Box::new(Value::U32(1)))),
1021 Value::Option(None),
1022 Value::Option(Some(Box::new(Value::String("test".to_string())))),
1023 ];
1024 assert_eq!(
1025 Value::from(option_array.clone()),
1026 Value::ArrayValue(option_array)
1027 );
1028 }
1029
1030 #[test]
1031 fn test_type_uuid() {
1032 use crate::ty;
1033
1034 assert_eq!(Value::Unit.type_uuid(), *ty::UNIT_ID);
1036 assert_eq!(Value::Boolean(false).type_uuid(), *ty::BOOLEAN_ID);
1037 assert_eq!(Value::I8(0).type_uuid(), *ty::I8_ID);
1038 assert_eq!(Value::I16(0).type_uuid(), *ty::I16_ID);
1039 assert_eq!(Value::I32(0).type_uuid(), *ty::I32_ID);
1040 assert_eq!(Value::I64(0).type_uuid(), *ty::I64_ID);
1041 assert_eq!(Value::U8(0).type_uuid(), *ty::U8_ID);
1042 assert_eq!(Value::U16(0).type_uuid(), *ty::U16_ID);
1043 assert_eq!(Value::U32(0).type_uuid(), *ty::U32_ID);
1044 assert_eq!(Value::U64(0).type_uuid(), *ty::U64_ID);
1045 assert_eq!(Value::F32(0.0).type_uuid(), *ty::F32_ID);
1046 assert_eq!(Value::F64(0.0).type_uuid(), *ty::F64_ID);
1047 assert_eq!(Value::String("".into()).type_uuid(), *ty::STRING_ID);
1048
1049 let test_id = uuid::Uuid::from_u128(0xdeadbeef);
1051 let variant_id = uuid::Uuid::from_u128(0xcafebabe);
1052
1053 assert_eq!(
1054 Value::Structure(Structure {
1055 id: test_id,
1056 fields: vec![],
1057 })
1058 .type_uuid(),
1059 test_id
1060 );
1061 assert_eq!(
1062 Value::Enumeration(Enumeration {
1063 id: test_id,
1064 variant_id,
1065 value: Box::new(Value::Unit),
1066 })
1067 .type_uuid(),
1068 test_id
1069 );
1070 assert_eq!(
1071 Value::ArrayStructure {
1072 id: test_id,
1073 elements: vec![],
1074 }
1075 .type_uuid(),
1076 test_id
1077 );
1078 assert_eq!(
1079 Value::ArrayEnumeration {
1080 id: test_id,
1081 elements: vec![],
1082 }
1083 .type_uuid(),
1084 test_id
1085 );
1086
1087 assert_eq!(Value::Option(None).type_uuid(), *ty::OPTION_ID);
1089 assert_eq!(
1090 Value::Option(Some(Box::new(Value::Unit))).type_uuid(),
1091 *ty::OPTION_ID
1092 );
1093 assert_eq!(
1094 Value::ArrayBoolean(vec![]).type_uuid(),
1095 *ty::ARRAY_BOOLEAN_ID
1096 );
1097 assert_eq!(Value::ArrayU8(vec![]).type_uuid(), *ty::ARRAY_U8_ID);
1098 assert_eq!(Value::ArrayU16(vec![]).type_uuid(), *ty::ARRAY_U16_ID);
1099 assert_eq!(Value::ArrayU32(vec![]).type_uuid(), *ty::ARRAY_U32_ID);
1100 assert_eq!(Value::ArrayU64(vec![]).type_uuid(), *ty::ARRAY_U64_ID);
1101 assert_eq!(Value::ArrayI8(vec![]).type_uuid(), *ty::ARRAY_I8_ID);
1102 assert_eq!(Value::ArrayI16(vec![]).type_uuid(), *ty::ARRAY_I16_ID);
1103 assert_eq!(Value::ArrayI32(vec![]).type_uuid(), *ty::ARRAY_I32_ID);
1104 assert_eq!(Value::ArrayI64(vec![]).type_uuid(), *ty::ARRAY_I64_ID);
1105 assert_eq!(Value::ArrayF32(vec![]).type_uuid(), *ty::ARRAY_F32_ID);
1106 assert_eq!(Value::ArrayF64(vec![]).type_uuid(), *ty::ARRAY_F64_ID);
1107 assert_eq!(Value::ArrayString(vec![]).type_uuid(), *ty::ARRAY_STRING_ID);
1108 assert_eq!(Value::ArrayValue(vec![]).type_uuid(), *ty::ARRAY_VALUE_ID);
1109 assert_eq!(
1110 Value::KeyValue(KeyValue::default()).type_uuid(),
1111 *ty::KEY_VALUE_ID
1112 );
1113 assert_eq!(Value::Uuid(uuid::Uuid::nil()).type_uuid(), *ty::UUID_ID);
1114
1115 let all_wellknown: Vec<uuid::Uuid> = ty::WELL_KNOWN_IDS.iter().copied().collect();
1117 assert_eq!(all_wellknown.len(), 29); }
1119}