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 kind(&self) -> Type {
193 match self {
194 Value::Unit => Type::Unit,
195 Value::Boolean(_) => Type::Boolean,
196 Value::U8(_) => Type::U8,
197 Value::U16(_) => Type::U16,
198 Value::U32(_) => Type::U32,
199 Value::U64(_) => Type::U64,
200 Value::I8(_) => Type::I8,
201 Value::I16(_) => Type::I16,
202 Value::I32(_) => Type::I32,
203 Value::I64(_) => Type::I64,
204 Value::F32(_) => Type::F32,
205 Value::F64(_) => Type::F64,
206 Value::String(_) => Type::String,
207 Value::Option(_) => Type::Option,
208 Value::Structure(_) => Type::Structure,
209 Value::Enumeration(_) => Type::Enumeration,
210 Value::ArrayBoolean(_) => Type::ArrayBoolean,
211 Value::ArrayU8(_) => Type::ArrayU8,
212 Value::ArrayU16(_) => Type::ArrayU16,
213 Value::ArrayU32(_) => Type::ArrayU32,
214 Value::ArrayU64(_) => Type::ArrayU64,
215 Value::ArrayI8(_) => Type::ArrayI8,
216 Value::ArrayI16(_) => Type::ArrayI16,
217 Value::ArrayI32(_) => Type::ArrayI32,
218 Value::ArrayI64(_) => Type::ArrayI64,
219 Value::ArrayF32(_) => Type::ArrayF32,
220 Value::ArrayF64(_) => Type::ArrayF64,
221 Value::ArrayString(_) => Type::ArrayString,
222 Value::ArrayValue(_) => Type::ArrayValue,
223 Value::ArrayStructure { .. } => Type::ArrayStructure,
224 Value::ArrayEnumeration { .. } => Type::ArrayEnumeration,
225 Value::KeyValue(_) => Type::KeyValue,
226 Value::Uuid(_) => Type::Uuid,
227 }
228 }
229
230 pub fn type_uuid(&self) -> Uuid {
236 use crate::ty;
237 match self {
238 Value::Unit => *ty::UNIT_ID,
239 Value::Boolean(_) => *ty::BOOLEAN_ID,
240 Value::I8(_) => *ty::I8_ID,
241 Value::I16(_) => *ty::I16_ID,
242 Value::I32(_) => *ty::I32_ID,
243 Value::I64(_) => *ty::I64_ID,
244 Value::U8(_) => *ty::U8_ID,
245 Value::U16(_) => *ty::U16_ID,
246 Value::U32(_) => *ty::U32_ID,
247 Value::U64(_) => *ty::U64_ID,
248 Value::F32(_) => *ty::F32_ID,
249 Value::F64(_) => *ty::F64_ID,
250 Value::String(_) => *ty::STRING_ID,
251 Value::Option(_) => *ty::OPTION_ID,
252 Value::Structure(s) => s.id,
253 Value::Enumeration(e) => e.id,
254 Value::ArrayBoolean(_) => *ty::ARRAY_BOOLEAN_ID,
255 Value::ArrayU8(_) => *ty::ARRAY_U8_ID,
256 Value::ArrayU16(_) => *ty::ARRAY_U16_ID,
257 Value::ArrayU32(_) => *ty::ARRAY_U32_ID,
258 Value::ArrayU64(_) => *ty::ARRAY_U64_ID,
259 Value::ArrayI8(_) => *ty::ARRAY_I8_ID,
260 Value::ArrayI16(_) => *ty::ARRAY_I16_ID,
261 Value::ArrayI32(_) => *ty::ARRAY_I32_ID,
262 Value::ArrayI64(_) => *ty::ARRAY_I64_ID,
263 Value::ArrayF32(_) => *ty::ARRAY_F32_ID,
264 Value::ArrayF64(_) => *ty::ARRAY_F64_ID,
265 Value::ArrayString(_) => *ty::ARRAY_STRING_ID,
266 Value::ArrayValue(_) => *ty::ARRAY_VALUE_ID,
267 Value::ArrayStructure { id, .. } => *id,
268 Value::ArrayEnumeration { id, .. } => *id,
269 Value::KeyValue(_) => *ty::KEY_VALUE_ID,
270 Value::Uuid(_) => *ty::UUID_ID,
271 }
272 }
273}
274
275#[derive(Debug, Clone, Display, Serialize, Deserialize, PartialEq)]
276#[display("{}::{}({})", id, variant_id, value)]
277pub struct Enumeration {
278 pub id: Uuid,
279 pub variant_id: Uuid,
280 pub value: Box<Value>,
281}
282
283#[derive(Debug, Clone, Display, Serialize, Deserialize, PartialEq)]
284#[display("{}({:?})", id, fields)]
285pub struct Structure {
286 pub id: Uuid,
287 pub fields: Vec<StructureField>,
288}
289
290#[derive(Debug, Clone, Display, Serialize, Deserialize, PartialEq)]
291#[display("{}: {}", id, value)]
292pub struct StructureField {
293 pub id: Uuid,
294 pub value: Box<Value>,
295}
296
297#[derive(Debug, Clone, Display, Serialize, Deserialize, PartialEq)]
298#[display("({:?})", fields)]
299pub struct StructureWithoutId {
300 pub fields: Vec<StructureField>,
302}
303
304#[derive(Debug, Clone, Display, Serialize, Deserialize, PartialEq)]
305#[display("{}({})", variant_id, value)]
306pub struct EnumerationWithoutId {
307 pub variant_id: Uuid,
308 pub value: Box<Value>,
309}
310
311#[derive(Display, Debug)]
313pub struct ConversionError {
314 pub message: String,
315}
316
317impl std::error::Error for ConversionError {}
318
319impl Value {
320 pub fn array_of(element_id: Uuid, elements: Vec<Value>) -> Value {
327 macro_rules! typed {
328 ($variant:ident, $array:ident) => {
329 if elements.iter().all(|v| matches!(v, Value::$variant(_))) {
330 return Value::$array(
331 elements
332 .into_iter()
333 .map(|v| match v {
334 Value::$variant(x) => x,
335 _ => unreachable!(),
336 })
337 .collect(),
338 );
339 }
340 };
341 }
342 if elements.is_empty() {
343 return Self::empty_array(element_id, false);
344 }
345 typed!(Boolean, ArrayBoolean);
346 typed!(U8, ArrayU8);
347 typed!(U16, ArrayU16);
348 typed!(U32, ArrayU32);
349 typed!(U64, ArrayU64);
350 typed!(I8, ArrayI8);
351 typed!(I16, ArrayI16);
352 typed!(I32, ArrayI32);
353 typed!(I64, ArrayI64);
354 typed!(F32, ArrayF32);
355 typed!(F64, ArrayF64);
356 typed!(String, ArrayString);
357 if elements.iter().all(|v| matches!(v, Value::Structure(_))) {
358 return Value::ArrayStructure {
359 id: element_id,
360 elements: elements
361 .into_iter()
362 .map(|v| match v {
363 Value::Structure(s) => StructureWithoutId { fields: s.fields },
364 _ => unreachable!(),
365 })
366 .collect(),
367 };
368 }
369 if elements.iter().all(|v| matches!(v, Value::Enumeration(_))) {
370 return Value::ArrayEnumeration {
371 id: element_id,
372 elements: elements
373 .into_iter()
374 .map(|v| match v {
375 Value::Enumeration(e) => EnumerationWithoutId {
376 variant_id: e.variant_id,
377 value: e.value,
378 },
379 _ => unreachable!(),
380 })
381 .collect(),
382 };
383 }
384 Value::ArrayValue(elements)
385 }
386
387 pub fn array_of_type<T: crate::AroraType>(elements: Vec<Value>) -> Value {
390 if elements.is_empty() {
391 let enumeration = matches!(
392 T::arora_type().kind,
393 crate::ty::low::TypeKind::Enumeration(_)
394 );
395 return Self::empty_array(T::arora_type_id(), enumeration);
396 }
397 Self::array_of(T::arora_type_id(), elements)
398 }
399
400 fn empty_array(element_id: Uuid, enumeration: bool) -> Value {
401 let id = &element_id;
402 if id == &*crate::ty::BOOLEAN_ID {
403 Value::ArrayBoolean(vec![])
404 } else if id == &*crate::ty::U8_ID {
405 Value::ArrayU8(vec![])
406 } else if id == &*crate::ty::U16_ID {
407 Value::ArrayU16(vec![])
408 } else if id == &*crate::ty::U32_ID {
409 Value::ArrayU32(vec![])
410 } else if id == &*crate::ty::U64_ID {
411 Value::ArrayU64(vec![])
412 } else if id == &*crate::ty::I8_ID {
413 Value::ArrayI8(vec![])
414 } else if id == &*crate::ty::I16_ID {
415 Value::ArrayI16(vec![])
416 } else if id == &*crate::ty::I32_ID {
417 Value::ArrayI32(vec![])
418 } else if id == &*crate::ty::I64_ID {
419 Value::ArrayI64(vec![])
420 } else if id == &*crate::ty::F32_ID {
421 Value::ArrayF32(vec![])
422 } else if id == &*crate::ty::F64_ID {
423 Value::ArrayF64(vec![])
424 } else if id == &*crate::ty::STRING_ID {
425 Value::ArrayString(vec![])
426 } else if id == &*crate::ty::UUID_ID || id == &*crate::ty::KEY_VALUE_ID {
427 Value::ArrayValue(vec![])
428 } else if enumeration {
429 Value::ArrayEnumeration {
430 id: element_id,
431 elements: vec![],
432 }
433 } else {
434 Value::ArrayStructure {
435 id: element_id,
436 elements: vec![],
437 }
438 }
439 }
440
441 pub fn into_elements(self) -> Result<Vec<Value>, String> {
445 macro_rules! typed {
446 ($array:ident, $variant:ident, $v:expr) => {
447 $v.into_iter().map(Value::$variant).collect()
448 };
449 }
450 Ok(match self {
451 Value::ArrayBoolean(v) => typed!(ArrayBoolean, Boolean, v),
452 Value::ArrayU8(v) => typed!(ArrayU8, U8, v),
453 Value::ArrayU16(v) => typed!(ArrayU16, U16, v),
454 Value::ArrayU32(v) => typed!(ArrayU32, U32, v),
455 Value::ArrayU64(v) => typed!(ArrayU64, U64, v),
456 Value::ArrayI8(v) => typed!(ArrayI8, I8, v),
457 Value::ArrayI16(v) => typed!(ArrayI16, I16, v),
458 Value::ArrayI32(v) => typed!(ArrayI32, I32, v),
459 Value::ArrayI64(v) => typed!(ArrayI64, I64, v),
460 Value::ArrayF32(v) => typed!(ArrayF32, F32, v),
461 Value::ArrayF64(v) => typed!(ArrayF64, F64, v),
462 Value::ArrayString(v) => typed!(ArrayString, String, v),
463 Value::ArrayValue(v) => v,
464 Value::ArrayStructure { id, elements } => elements
465 .into_iter()
466 .map(|e| {
467 Value::Structure(Structure {
468 id,
469 fields: e.fields,
470 })
471 })
472 .collect(),
473 Value::ArrayEnumeration { id, elements } => elements
474 .into_iter()
475 .map(|e| {
476 Value::Enumeration(Enumeration {
477 id,
478 variant_id: e.variant_id,
479 value: e.value,
480 })
481 })
482 .collect(),
483 other => return Err(format!("expected an array, got {other}")),
484 })
485 }
486}
487
488impl From<()> for Value {
489 fn from(_: ()) -> Self {
490 Value::Unit
491 }
492}
493
494impl From<bool> for Value {
495 fn from(v: bool) -> Self {
496 Value::Boolean(v)
497 }
498}
499
500impl From<u8> for Value {
501 fn from(v: u8) -> Self {
502 Value::U8(v)
503 }
504}
505
506impl From<u16> for Value {
507 fn from(v: u16) -> Self {
508 Value::U16(v)
509 }
510}
511
512impl From<u32> for Value {
513 fn from(v: u32) -> Self {
514 Value::U32(v)
515 }
516}
517
518impl From<u64> for Value {
519 fn from(v: u64) -> Self {
520 Value::U64(v)
521 }
522}
523
524impl From<i8> for Value {
525 fn from(v: i8) -> Self {
526 Value::I8(v)
527 }
528}
529
530impl From<i16> for Value {
531 fn from(v: i16) -> Self {
532 Value::I16(v)
533 }
534}
535
536impl From<i32> for Value {
537 fn from(v: i32) -> Self {
538 Value::I32(v)
539 }
540}
541
542impl From<i64> for Value {
543 fn from(v: i64) -> Self {
544 Value::I64(v)
545 }
546}
547
548impl From<f32> for Value {
549 fn from(v: f32) -> Self {
550 Value::F32(v)
551 }
552}
553
554impl From<f64> for Value {
555 fn from(v: f64) -> Self {
556 Value::F64(v)
557 }
558}
559
560impl From<String> for Value {
561 fn from(v: String) -> Self {
562 Value::String(v)
563 }
564}
565
566impl From<&str> for Value {
567 fn from(v: &str) -> Self {
568 Value::String(v.to_string())
569 }
570}
571
572impl From<Uuid> for Value {
573 fn from(v: Uuid) -> Self {
574 Value::Uuid(v)
575 }
576}
577
578impl<T> From<Option<T>> for Value
580where
581 T: Into<Value>,
582{
583 fn from(opt: Option<T>) -> Self {
584 match opt {
585 Some(value) => Value::Option(Some(Box::new(value.into()))),
586 None => Value::Option(None),
587 }
588 }
589}
590
591impl From<Vec<Value>> for Value {
593 fn from(vec: Vec<Value>) -> Self {
594 Value::ArrayValue(vec)
595 }
596}
597
598impl From<&[Value]> for Value {
600 fn from(slice: &[Value]) -> Self {
601 Value::ArrayValue(slice.to_vec())
602 }
603}
604
605macro_rules! impl_array_conversions {
607 ($(($rust_type:ty, $variant:ident)),* $(,)?) => {
608 $(
609 impl From<Vec<$rust_type>> for Value {
611 fn from(vec: Vec<$rust_type>) -> Self {
612 Value::$variant(vec)
613 }
614 }
615
616 impl From<&[$rust_type]> for Value {
618 fn from(slice: &[$rust_type]) -> Self {
619 Value::$variant(slice.to_vec())
620 }
621 }
622
623 impl From<std::collections::HashSet<$rust_type>> for Value {
625 fn from(set: std::collections::HashSet<$rust_type>) -> Self {
626 Value::$variant(set.into_iter().collect())
627 }
628 }
629 )*
630 };
631}
632
633impl_array_conversions! {
635 (bool, ArrayBoolean),
636 (u8, ArrayU8),
637 (u16, ArrayU16),
638 (u32, ArrayU32),
639 (u64, ArrayU64),
640 (i8, ArrayI8),
641 (i16, ArrayI16),
642 (i32, ArrayI32),
643 (i64, ArrayI64),
644 (String, ArrayString),
645}
646
647macro_rules! impl_float_array_conversions {
649 ($(($rust_type:ty, $variant:ident)),* $(,)?) => {
650 $(
651 impl From<Vec<$rust_type>> for Value {
653 fn from(vec: Vec<$rust_type>) -> Self {
654 Value::$variant(vec)
655 }
656 }
657
658 impl From<&[$rust_type]> for Value {
660 fn from(slice: &[$rust_type]) -> Self {
661 Value::$variant(slice.to_vec())
662 }
663 }
664 )*
665 };
666}
667
668impl_float_array_conversions! {
670 (f32, ArrayF32),
671 (f64, ArrayF64),
672}
673
674#[cfg(test)]
677mod tests {
678 use super::*;
679 use json5;
680 use pretty_assertions::assert_eq;
681
682 fn test_serde_roundtrip<T>(value: &T, name: &str)
684 where
685 T: Serialize + for<'de> Deserialize<'de> + PartialEq + std::fmt::Debug + Clone,
686 {
687 let json = json5::to_string(value).unwrap();
689 println!("{} JSON:\n{}", name, json);
690
691 let deserialized: T = json5::from_str(&json).unwrap();
692 assert_eq!(
693 value, &deserialized,
694 "Roundtrip JSON serialization failed for {name}"
695 );
696
697 let ron = ron::to_string(value).unwrap();
699 println!("{} RON:\n{}", name, ron);
700 let deserialized: T = ron::from_str(&ron).unwrap();
701 assert_eq!(
702 value, &deserialized,
703 "Roundtrip RON serialization failed for {name}"
704 );
705 }
706
707 #[test]
711 fn value_round_trips_through_yaml() {
712 let value = Value::Structure(Structure {
713 id: Uuid::from_u128(0x10),
714 fields: vec![
715 StructureField {
716 id: Uuid::from_u128(0x01),
717 value: Box::new(Value::ArrayF64(vec![1.0, -2.0, 3.5])),
718 },
719 StructureField {
720 id: Uuid::from_u128(0x02),
721 value: Box::new(Value::String("hi".to_string())),
722 },
723 ],
724 });
725 let yaml = serde_yaml::to_string(&value).unwrap();
726 let back: Value = serde_yaml::from_str(&yaml).unwrap();
727 assert_eq!(value, back, "Value did not round-trip through YAML");
728 }
729
730 #[test]
731 fn test_type_serialization() {
732 for typ in [
734 Type::Unit,
735 Type::Boolean,
736 Type::U8,
737 Type::U16,
738 Type::U32,
739 Type::U64,
740 Type::I8,
741 Type::I16,
742 Type::I32,
743 Type::I64,
744 Type::F32,
745 Type::F64,
746 Type::String,
747 Type::Option,
748 Type::Structure,
749 Type::Enumeration,
750 Type::ArrayBoolean,
751 Type::ArrayU8,
752 Type::ArrayU16,
753 Type::ArrayU32,
754 Type::ArrayU64,
755 Type::ArrayI8,
756 Type::ArrayI16,
757 Type::ArrayI32,
758 Type::ArrayI64,
759 Type::ArrayF32,
760 Type::ArrayF64,
761 Type::ArrayString,
762 Type::ArrayValue,
763 Type::ArrayStructure,
764 Type::ArrayEnumeration,
765 Type::KeyValue,
766 Type::Uuid,
767 ] {
768 test_serde_roundtrip(&typ, &format!("Type::{:?}", typ));
769 }
770 }
771
772 #[test]
773 fn test_value_primitive_serialization() {
774 let primitives = vec![
776 ("Unit", Value::Unit),
777 ("Boolean_true", Value::Boolean(true)),
778 ("Boolean_false", Value::Boolean(false)),
779 ("U8_min", Value::U8(0)),
780 ("U8_max", Value::U8(u8::MAX)),
781 ("U16_max", Value::U16(u16::MAX)),
782 ("U32_max", Value::U32(u32::MAX)),
783 ("U64_max", Value::U64(u64::MAX)),
784 ("I8_min", Value::I8(i8::MIN)),
785 ("I8_max", Value::I8(i8::MAX)),
786 ("I16_min", Value::I16(i16::MIN)),
787 ("I32_min", Value::I32(i32::MIN)),
788 ("I64_min", Value::I64(i64::MIN)),
789 ("F32_zero", Value::F32(0.0)),
790 ("F32_inf", Value::F32(f32::INFINITY)),
791 ("F32_neg_inf", Value::F32(f32::NEG_INFINITY)),
792 ("F64_zero", Value::F64(0.0)),
793 ("F64_inf", Value::F64(f64::INFINITY)),
794 ("F64_neg_inf", Value::F64(f64::NEG_INFINITY)),
795 ("String_empty", Value::String("".to_string())),
796 ("String_hello", Value::String("Hello, world!".to_string())),
797 (
798 "String_special",
799 Value::String("Special chars: \n\t\r\"\\".to_string()),
800 ),
801 ];
802
803 for (name, value) in primitives {
804 test_serde_roundtrip(&value, name);
805 }
806
807 let f32_nan = Value::F32(f32::NAN);
809 let f32_json = json5::to_string(&f32_nan).unwrap();
810 println!("F32_NaN JSON:\n{}", f32_json);
811 let deserialized_f32: Value = json5::from_str(&f32_json).unwrap();
812 if let Value::F32(val) = deserialized_f32 {
813 assert!(val.is_nan(), "Deserialized F32 should be NaN");
814 }
815
816 let f64_nan = Value::F64(f64::NAN);
817 let f64_json = json5::to_string(&f64_nan).unwrap();
818 println!("F64_NaN JSON:\n{}", f64_json);
819 let deserialized_f64: Value = json5::from_str(&f64_json).unwrap();
820 if let Value::F64(val) = deserialized_f64 {
821 assert!(val.is_nan(), "Deserialized F64 should be NaN");
822 }
823 }
824
825 #[test]
826 fn test_value_array_serialization() {
827 let arrays = vec![
829 ("ArrayBoolean_empty", Value::ArrayBoolean(vec![])),
830 ("ArrayBoolean", Value::ArrayBoolean(vec![true, false])),
831 ("ArrayU8", Value::ArrayU8(vec![0, 123, 255])),
832 ("ArrayI32", Value::ArrayI32(vec![i32::MIN, 0, i32::MAX])),
833 (
834 "ArrayF64",
835 Value::ArrayF64(vec![-1.0, 0.0, 1.0, f64::INFINITY]),
836 ),
837 (
838 "ArrayString",
839 Value::ArrayString(vec!["a".to_string(), "b".to_string()]),
840 ),
841 ];
842
843 for (name, value) in arrays {
844 test_serde_roundtrip(&value, name);
845 }
846 }
847
848 #[test]
849 fn test_structure_field_serialization() {
850 let field = StructureField {
851 id: Uuid::parse_str("550e8400-e29b-41d4-a716-446655440000").unwrap(),
852 value: Box::new(Value::String("test field".to_string())),
853 };
854
855 test_serde_roundtrip(&field, "StructureField");
856 }
857
858 #[test]
859 fn test_structure_serialization() {
860 let empty_structure = Structure {
862 id: Uuid::parse_str("550e8400-e29b-41d4-a716-446655440000").unwrap(),
863 fields: vec![],
864 };
865
866 test_serde_roundtrip(&empty_structure, "EmptyStructure");
867
868 let structure = Structure {
870 id: Uuid::parse_str("550e8400-e29b-41d4-a716-446655440000").unwrap(),
871 fields: vec![
872 StructureField {
873 id: Uuid::parse_str("550e8400-e29b-41d4-a716-446655440001").unwrap(),
874 value: Box::new(Value::String("field1".to_string())),
875 },
876 StructureField {
877 id: Uuid::parse_str("550e8400-e29b-41d4-a716-446655440002").unwrap(),
878 value: Box::new(Value::I32(42)),
879 },
880 ],
881 };
882
883 test_serde_roundtrip(&structure, "Structure");
884 }
885
886 #[test]
887 fn test_structure_without_id_serialization() {
888 let structure_without_id = StructureWithoutId {
889 fields: vec![StructureField {
890 id: Uuid::parse_str("550e8400-e29b-41d4-a716-446655440001").unwrap(),
891 value: Box::new(Value::String("field1".to_string())),
892 }],
893 };
894
895 test_serde_roundtrip(&structure_without_id, "StructureWithoutId");
896 }
897
898 #[test]
899 fn test_enumeration_serialization() {
900 let enumeration = Enumeration {
901 id: Uuid::parse_str("550e8400-e29b-41d4-a716-446655440000").unwrap(),
902 variant_id: Uuid::parse_str("550e8400-e29b-41d4-a716-446655440001").unwrap(),
903 value: Box::new(Value::String("variant value".to_string())),
904 };
905
906 test_serde_roundtrip(&enumeration, "Enumeration");
907 }
908
909 #[test]
910 fn test_enumeration_without_id_serialization() {
911 let enumeration_without_id = EnumerationWithoutId {
912 variant_id: Uuid::parse_str("550e8400-e29b-41d4-a716-446655440001").unwrap(),
913 value: Box::new(Value::String("variant value".to_string())),
914 };
915
916 test_serde_roundtrip(&enumeration_without_id, "EnumerationWithoutId");
917 }
918
919 #[test]
920 fn test_complex_nested_values() {
921 let complex_value = Value::Structure(Structure {
923 id: Uuid::parse_str("550e8400-e29b-41d4-a716-446655440000").unwrap(),
924 fields: vec![
925 StructureField {
926 id: Uuid::parse_str("550e8400-e29b-41d4-a716-446655440001").unwrap(),
927 value: Box::new(Value::String("name".to_string())),
928 },
929 StructureField {
930 id: Uuid::parse_str("550e8400-e29b-41d4-a716-446655440002").unwrap(),
931 value: Box::new(Value::Enumeration(Enumeration {
932 id: Uuid::parse_str("550e8400-e29b-41d4-a716-446655440003").unwrap(),
933 variant_id: Uuid::parse_str("550e8400-e29b-41d4-a716-446655440004").unwrap(),
934 value: Box::new(Value::Boolean(true)),
935 })),
936 },
937 ],
938 });
939
940 test_serde_roundtrip(&complex_value, "ComplexNestedValue");
941 }
942
943 #[test]
944 fn test_array_structure_and_enumeration() {
945 let array_structure = Value::ArrayStructure {
947 id: Uuid::parse_str("550e8400-e29b-41d4-a716-446655440000").unwrap(),
948 elements: vec![
949 StructureWithoutId {
950 fields: vec![StructureField {
951 id: Uuid::parse_str("550e8400-e29b-41d4-a716-446655440001").unwrap(),
952 value: Box::new(Value::String("element1".to_string())),
953 }],
954 },
955 StructureWithoutId { fields: vec![] }, ],
957 };
958
959 test_serde_roundtrip(&array_structure, "ArrayStructure");
960
961 let array_enumeration = Value::ArrayEnumeration {
963 id: Uuid::parse_str("550e8400-e29b-41d4-a716-446655440000").unwrap(),
964 elements: vec![
965 EnumerationWithoutId {
966 variant_id: Uuid::parse_str("550e8400-e29b-41d4-a716-446655440001").unwrap(),
967 value: Box::new(Value::String("variant1".to_string())),
968 },
969 EnumerationWithoutId {
970 variant_id: Uuid::parse_str("550e8400-e29b-41d4-a716-446655440002").unwrap(),
971 value: Box::new(Value::U32(42)),
972 },
973 ],
974 };
975
976 test_serde_roundtrip(&array_enumeration, "ArrayEnumeration");
977 }
978
979 #[test]
980 fn test_from_conversions_primitives() {
981 assert_eq!(Value::from(()), Value::Unit);
983 assert_eq!(Value::from(true), Value::Boolean(true));
984 assert_eq!(Value::from(false), Value::Boolean(false));
985
986 assert_eq!(Value::from(42u8), Value::U8(42));
987 assert_eq!(Value::from(1234u16), Value::U16(1234));
988 assert_eq!(Value::from(123456u32), Value::U32(123456));
989 assert_eq!(Value::from(12345678901234u64), Value::U64(12345678901234));
990
991 assert_eq!(Value::from(-42i8), Value::I8(-42));
992 assert_eq!(Value::from(-1234i16), Value::I16(-1234));
993 assert_eq!(Value::from(-123456i32), Value::I32(-123456));
994 assert_eq!(Value::from(-12345678901234i64), Value::I64(-12345678901234));
995
996 assert_eq!(
997 Value::from(std::f32::consts::PI),
998 Value::F32(std::f32::consts::PI)
999 );
1000 assert_eq!(
1001 Value::from(std::f64::consts::PI),
1002 Value::F64(std::f64::consts::PI)
1003 );
1004
1005 assert_eq!(
1006 Value::from("hello".to_string()),
1007 Value::String("hello".to_string())
1008 );
1009 assert_eq!(Value::from("world"), Value::String("world".to_string()));
1010
1011 let uuid = Uuid::parse_str("550e8400-e29b-41d4-a716-446655440000").unwrap();
1012 assert_eq!(Value::from(uuid), Value::Uuid(uuid));
1013 }
1014
1015 #[test]
1016 fn test_from_conversions_arrays_vec() {
1017 assert_eq!(
1019 Value::from(vec![true, false, true]),
1020 Value::ArrayBoolean(vec![true, false, true])
1021 );
1022 assert_eq!(
1023 Value::from(vec![1u8, 2u8, 3u8]),
1024 Value::ArrayU8(vec![1, 2, 3])
1025 );
1026 assert_eq!(
1027 Value::from(vec![100u16, 200u16]),
1028 Value::ArrayU16(vec![100, 200])
1029 );
1030 assert_eq!(
1031 Value::from(vec![1000u32, 2000u32]),
1032 Value::ArrayU32(vec![1000, 2000])
1033 );
1034 assert_eq!(
1035 Value::from(vec![10000u64, 20000u64]),
1036 Value::ArrayU64(vec![10000, 20000])
1037 );
1038
1039 assert_eq!(Value::from(vec![-1i8, -2i8]), Value::ArrayI8(vec![-1, -2]));
1040 assert_eq!(
1041 Value::from(vec![-100i16, -200i16]),
1042 Value::ArrayI16(vec![-100, -200])
1043 );
1044 assert_eq!(
1045 Value::from(vec![-1000i32, -2000i32]),
1046 Value::ArrayI32(vec![-1000, -2000])
1047 );
1048 assert_eq!(
1049 Value::from(vec![-10000i64, -20000i64]),
1050 Value::ArrayI64(vec![-10000, -20000])
1051 );
1052
1053 assert_eq!(
1054 Value::from(vec![1.5f32, 2.5f32]),
1055 Value::ArrayF32(vec![1.5, 2.5])
1056 );
1057 assert_eq!(
1058 Value::from(vec![1.5f64, 2.5f64]),
1059 Value::ArrayF64(vec![1.5, 2.5])
1060 );
1061
1062 assert_eq!(
1063 Value::from(vec!["hello".to_string(), "world".to_string()]),
1064 Value::ArrayString(vec!["hello".to_string(), "world".to_string()])
1065 );
1066 }
1067
1068 #[test]
1069 fn test_from_conversions_arrays_slices() {
1070 let bool_slice = &[true, false, true][..];
1072 assert_eq!(
1073 Value::from(bool_slice),
1074 Value::ArrayBoolean(vec![true, false, true])
1075 );
1076
1077 let u32_slice = &[1u32, 2u32, 3u32][..];
1078 assert_eq!(Value::from(u32_slice), Value::ArrayU32(vec![1, 2, 3]));
1079
1080 let string_slice = &["a".to_string(), "b".to_string()][..];
1081 assert_eq!(
1082 Value::from(string_slice),
1083 Value::ArrayString(vec!["a".to_string(), "b".to_string()])
1084 );
1085 }
1086
1087 #[test]
1088 fn test_from_conversions_hashset() {
1089 use std::collections::HashSet;
1090
1091 let bool_set: HashSet<bool> = [true, false].into_iter().collect();
1093 if let Value::ArrayBoolean(vec) = Value::from(bool_set) {
1094 assert_eq!(vec.len(), 2);
1095 assert!(vec.contains(&true));
1096 assert!(vec.contains(&false));
1097 } else {
1098 panic!("Expected ArrayBoolean");
1099 }
1100
1101 let u32_set: HashSet<u32> = [1, 2, 3].into_iter().collect();
1102 if let Value::ArrayU32(vec) = Value::from(u32_set) {
1103 assert_eq!(vec.len(), 3);
1104 assert!(vec.contains(&1));
1105 assert!(vec.contains(&2));
1106 assert!(vec.contains(&3));
1107 } else {
1108 panic!("Expected ArrayU32");
1109 }
1110
1111 let string_set: HashSet<String> = ["a".to_string(), "b".to_string()].into_iter().collect();
1112 if let Value::ArrayString(vec) = Value::from(string_set) {
1113 assert_eq!(vec.len(), 2);
1114 assert!(vec.contains(&"a".to_string()));
1115 assert!(vec.contains(&"b".to_string()));
1116 } else {
1117 panic!("Expected ArrayString");
1118 }
1119
1120 let empty_set: HashSet<u32> = HashSet::new();
1122 assert_eq!(Value::from(empty_set), Value::ArrayU32(vec![]));
1123 }
1124
1125 #[test]
1126 fn test_from_conversions_empty_arrays() {
1127 assert_eq!(Value::from(Vec::<bool>::new()), Value::ArrayBoolean(vec![]));
1129 assert_eq!(Value::from(Vec::<u8>::new()), Value::ArrayU8(vec![]));
1130 assert_eq!(Value::from(Vec::<u16>::new()), Value::ArrayU16(vec![]));
1131 assert_eq!(Value::from(Vec::<u32>::new()), Value::ArrayU32(vec![]));
1132 assert_eq!(Value::from(Vec::<u64>::new()), Value::ArrayU64(vec![]));
1133 assert_eq!(Value::from(Vec::<i8>::new()), Value::ArrayI8(vec![]));
1134 assert_eq!(Value::from(Vec::<i16>::new()), Value::ArrayI16(vec![]));
1135 assert_eq!(Value::from(Vec::<i32>::new()), Value::ArrayI32(vec![]));
1136 assert_eq!(Value::from(Vec::<i64>::new()), Value::ArrayI64(vec![]));
1137 assert_eq!(Value::from(Vec::<f32>::new()), Value::ArrayF32(vec![]));
1138 assert_eq!(Value::from(Vec::<f64>::new()), Value::ArrayF64(vec![]));
1139 assert_eq!(
1140 Value::from(Vec::<String>::new()),
1141 Value::ArrayString(vec![])
1142 );
1143 }
1144
1145 #[test]
1146 fn test_from_conversions_option() {
1147 assert_eq!(
1151 Value::from(Some(42u32)),
1152 Value::Option(Some(Box::new(Value::U32(42))))
1153 );
1154 assert_eq!(
1155 Value::from(Some(true)),
1156 Value::Option(Some(Box::new(Value::Boolean(true))))
1157 );
1158 assert_eq!(
1159 Value::from(Some("hello".to_string())),
1160 Value::Option(Some(Box::new(Value::String("hello".to_string()))))
1161 );
1162 assert_eq!(
1163 Value::from(Some(std::f64::consts::PI)),
1164 Value::Option(Some(Box::new(Value::F64(std::f64::consts::PI))))
1165 );
1166
1167 assert_eq!(Value::from(None::<u32>), Value::Option(None));
1169 assert_eq!(Value::from(None::<bool>), Value::Option(None));
1170 assert_eq!(Value::from(None::<String>), Value::Option(None));
1171 assert_eq!(Value::from(None::<f64>), Value::Option(None));
1172
1173 let nested_value = Value::ArrayU32(vec![1, 2, 3]);
1175 assert_eq!(
1176 Value::from(Some(nested_value.clone())),
1177 Value::Option(Some(Box::new(nested_value)))
1178 );
1179 assert_eq!(Value::from(None::<Value>), Value::Option(None));
1180 }
1181
1182 #[test]
1183 fn test_from_conversions_array_value() {
1184 assert_eq!(Value::from(Vec::<Value>::new()), Value::ArrayValue(vec![]));
1188
1189 let mixed_values = vec![
1191 Value::U32(42),
1192 Value::Boolean(true),
1193 Value::String("test".to_string()),
1194 Value::F64(std::f64::consts::PI),
1195 Value::Unit,
1196 ];
1197 assert_eq!(
1198 Value::from(mixed_values.clone()),
1199 Value::ArrayValue(mixed_values.clone())
1200 );
1201
1202 let values_slice = &[
1204 Value::I32(-10),
1205 Value::Boolean(false),
1206 Value::String("slice".to_string()),
1207 ][..];
1208 assert_eq!(
1209 Value::from(values_slice),
1210 Value::ArrayValue(vec![
1211 Value::I32(-10),
1212 Value::Boolean(false),
1213 Value::String("slice".to_string()),
1214 ])
1215 );
1216
1217 let nested_array = vec![
1219 Value::ArrayU32(vec![1, 2, 3]),
1220 Value::ArrayString(vec!["a".to_string(), "b".to_string()]),
1221 Value::ArrayBoolean(vec![true, false]),
1222 ];
1223 assert_eq!(
1224 Value::from(nested_array.clone()),
1225 Value::ArrayValue(nested_array)
1226 );
1227
1228 let option_array = vec![
1230 Value::Option(Some(Box::new(Value::U32(1)))),
1231 Value::Option(None),
1232 Value::Option(Some(Box::new(Value::String("test".to_string())))),
1233 ];
1234 assert_eq!(
1235 Value::from(option_array.clone()),
1236 Value::ArrayValue(option_array)
1237 );
1238 }
1239
1240 #[test]
1241 fn test_type_uuid() {
1242 use crate::ty;
1243
1244 assert_eq!(Value::Unit.type_uuid(), *ty::UNIT_ID);
1246 assert_eq!(Value::Boolean(false).type_uuid(), *ty::BOOLEAN_ID);
1247 assert_eq!(Value::I8(0).type_uuid(), *ty::I8_ID);
1248 assert_eq!(Value::I16(0).type_uuid(), *ty::I16_ID);
1249 assert_eq!(Value::I32(0).type_uuid(), *ty::I32_ID);
1250 assert_eq!(Value::I64(0).type_uuid(), *ty::I64_ID);
1251 assert_eq!(Value::U8(0).type_uuid(), *ty::U8_ID);
1252 assert_eq!(Value::U16(0).type_uuid(), *ty::U16_ID);
1253 assert_eq!(Value::U32(0).type_uuid(), *ty::U32_ID);
1254 assert_eq!(Value::U64(0).type_uuid(), *ty::U64_ID);
1255 assert_eq!(Value::F32(0.0).type_uuid(), *ty::F32_ID);
1256 assert_eq!(Value::F64(0.0).type_uuid(), *ty::F64_ID);
1257 assert_eq!(Value::String("".into()).type_uuid(), *ty::STRING_ID);
1258
1259 let test_id = uuid::Uuid::from_u128(0xdeadbeef);
1261 let variant_id = uuid::Uuid::from_u128(0xcafebabe);
1262
1263 assert_eq!(
1264 Value::Structure(Structure {
1265 id: test_id,
1266 fields: vec![],
1267 })
1268 .type_uuid(),
1269 test_id
1270 );
1271 assert_eq!(
1272 Value::Enumeration(Enumeration {
1273 id: test_id,
1274 variant_id,
1275 value: Box::new(Value::Unit),
1276 })
1277 .type_uuid(),
1278 test_id
1279 );
1280 assert_eq!(
1281 Value::ArrayStructure {
1282 id: test_id,
1283 elements: vec![],
1284 }
1285 .type_uuid(),
1286 test_id
1287 );
1288 assert_eq!(
1289 Value::ArrayEnumeration {
1290 id: test_id,
1291 elements: vec![],
1292 }
1293 .type_uuid(),
1294 test_id
1295 );
1296
1297 assert_eq!(Value::Option(None).type_uuid(), *ty::OPTION_ID);
1299 assert_eq!(
1300 Value::Option(Some(Box::new(Value::Unit))).type_uuid(),
1301 *ty::OPTION_ID
1302 );
1303 assert_eq!(
1304 Value::ArrayBoolean(vec![]).type_uuid(),
1305 *ty::ARRAY_BOOLEAN_ID
1306 );
1307 assert_eq!(Value::ArrayU8(vec![]).type_uuid(), *ty::ARRAY_U8_ID);
1308 assert_eq!(Value::ArrayU16(vec![]).type_uuid(), *ty::ARRAY_U16_ID);
1309 assert_eq!(Value::ArrayU32(vec![]).type_uuid(), *ty::ARRAY_U32_ID);
1310 assert_eq!(Value::ArrayU64(vec![]).type_uuid(), *ty::ARRAY_U64_ID);
1311 assert_eq!(Value::ArrayI8(vec![]).type_uuid(), *ty::ARRAY_I8_ID);
1312 assert_eq!(Value::ArrayI16(vec![]).type_uuid(), *ty::ARRAY_I16_ID);
1313 assert_eq!(Value::ArrayI32(vec![]).type_uuid(), *ty::ARRAY_I32_ID);
1314 assert_eq!(Value::ArrayI64(vec![]).type_uuid(), *ty::ARRAY_I64_ID);
1315 assert_eq!(Value::ArrayF32(vec![]).type_uuid(), *ty::ARRAY_F32_ID);
1316 assert_eq!(Value::ArrayF64(vec![]).type_uuid(), *ty::ARRAY_F64_ID);
1317 assert_eq!(Value::ArrayString(vec![]).type_uuid(), *ty::ARRAY_STRING_ID);
1318 assert_eq!(Value::ArrayValue(vec![]).type_uuid(), *ty::ARRAY_VALUE_ID);
1319 assert_eq!(
1320 Value::KeyValue(KeyValue::default()).type_uuid(),
1321 *ty::KEY_VALUE_ID
1322 );
1323 assert_eq!(Value::Uuid(uuid::Uuid::nil()).type_uuid(), *ty::UUID_ID);
1324
1325 let all_wellknown: Vec<uuid::Uuid> = ty::WELL_KNOWN_IDS.iter().copied().collect();
1327 assert_eq!(all_wellknown.len(), 29); }
1329}