compact binary serialization format with built-in compression
1use hateno::{Tag, TagKind};
2use hateno_serde::{Result, from_tag, to_tag};
3use serde::{Deserialize, Serialize};
4
5#[derive(Debug, Serialize, Deserialize, PartialEq)]
6struct TestStruct {
7 name: String,
8 age: u32,
9 active: bool,
10 scores: Vec<f32>,
11}
12
13#[derive(Debug, Serialize, Deserialize, PartialEq)]
14enum TestEnum {
15 Unit,
16 Newtype(String),
17 Tuple(u32, bool),
18 Struct { x: i32, y: i32 },
19}
20
21#[test]
22fn test_serialize_deserialize_struct() {
23 let original = TestStruct {
24 name: "Alice".to_string(),
25 age: 30,
26 active: true,
27 scores: vec![85.5, 92.0, 78.3],
28 };
29
30 let tag = to_tag(&original).unwrap();
31 let deserialized: TestStruct = from_tag(tag).unwrap();
32
33 assert_eq!(original, deserialized);
34}
35
36#[test]
37fn test_serialize_deserialize_primitives() {
38 assert_eq!(42u32, from_tag(to_tag(&42u32).unwrap()).unwrap());
39 assert_eq!(3.14f64, from_tag(to_tag(&3.14f64).unwrap()).unwrap());
40 assert_eq!(true, from_tag(to_tag(&true).unwrap()).unwrap());
41 assert_eq!(
42 "hello",
43 from_tag::<String>(to_tag(&"hello").unwrap()).unwrap()
44 );
45}
46
47#[test]
48fn test_serialize_deserialize_option() {
49 let some_value: Option<i32> = Some(42);
50 let none_value: Option<i32> = None;
51
52 assert_eq!(some_value, from_tag(to_tag(&some_value).unwrap()).unwrap());
53 assert_eq!(none_value, from_tag(to_tag(&none_value).unwrap()).unwrap());
54}
55
56#[test]
57fn test_serialize_deserialize_vec() {
58 let vec = vec![1, 2, 3, 4, 5];
59 assert_eq!(vec, from_tag::<Vec<i32>>(to_tag(&vec).unwrap()).unwrap());
60}
61
62#[test]
63fn test_serialize_deserialize_enum() {
64 let variants = vec![
65 TestEnum::Unit,
66 TestEnum::Newtype("test".to_string()),
67 TestEnum::Tuple(42, true),
68 TestEnum::Struct { x: 10, y: 20 },
69 ];
70
71 for variant in variants {
72 let tag = to_tag(&variant).unwrap();
73 let deserialized: TestEnum = from_tag(tag).unwrap();
74 assert_eq!(variant, deserialized);
75 }
76}
77
78#[test]
79fn test_serialize_bytes() {
80 let bytes: &[u8] = b"hello world";
81 let tag = to_tag(&bytes).unwrap();
82
83 match &tag {
84 Tag::Array(TagKind::U8, elements) => {
85 assert_eq!(elements.len(), bytes.len());
86 for (i, element) in elements.iter().enumerate() {
87 match element {
88 Tag::U8(b) => assert_eq!(*b, bytes[i]),
89 _ => panic!("Expected U8 tag"),
90 }
91 }
92 }
93 _ => panic!("Expected byte array, got {:?}", tag),
94 }
95
96 let deserialized: Vec<u8> = from_tag(tag).unwrap();
97 assert_eq!(deserialized, bytes);
98}
99
100#[test]
101fn test_error_handling() {
102 // Try to deserialize a string as a number
103 let string_tag = Tag::new_string("not a number");
104 let result: Result<u32> = from_tag(string_tag);
105 assert!(result.is_err());
106
107 // Try to deserialize a number as a struct
108 let number_tag = Tag::new_u32(42);
109 let result: Result<TestStruct> = from_tag(number_tag);
110 assert!(result.is_err());
111}
112
113#[test]
114fn test_direct_tag_usage() {
115 // Test that we can create tags directly and deserialize them
116 let tag = Tag::new_map(vec![
117 (Tag::new_string("name"), Tag::new_string("Bob")),
118 (Tag::new_string("age"), Tag::new_u32(25)),
119 (Tag::new_string("active"), Tag::new_bool(false)),
120 (
121 Tag::new_string("scores"),
122 Tag::new_list(vec![Tag::new_f32(88.5), Tag::new_f32(91.2)]),
123 ),
124 ]);
125
126 let deserialized: TestStruct = from_tag(tag).unwrap();
127 assert_eq!(deserialized.name, "Bob");
128 assert_eq!(deserialized.age, 25);
129 assert_eq!(deserialized.active, false);
130 assert_eq!(deserialized.scores, vec![88.5, 91.2]);
131}