1
use alloc::borrow::Cow;
2
use alloc::vec;
3
use core::fmt::Debug;
4
use std::collections::BTreeMap;
5
use std::string::String;
6

            
7
use serde::{Deserialize, Serialize};
8

            
9
use crate::value::Value;
10
use crate::{dbg, println};
11

            
12
221
#[derive(Serialize, Deserialize, Default, Debug, PartialEq)]
13
struct StructOfEverything<'a> {
14
    str: Cow<'a, str>,
15
    bytes: serde_bytes::ByteBuf,
16
    char: char,
17
    u8: u8,
18
    u16: u16,
19
    u32: u32,
20
    u64: u64,
21
    u128: u128,
22
    usize: usize,
23
    i8: i8,
24
    i16: i16,
25
    i32: i32,
26
    i64: i64,
27
    i128: i128,
28
    isize: isize,
29
    bool: bool,
30
}
31

            
32
impl<'a> StructOfEverything<'a> {
33
4
    fn min() -> Self {
34
4
        Self {
35
4
            str: Cow::Borrowed("\0"),
36
4
            bytes: serde_bytes::ByteBuf::from(vec![0]),
37
4
            char: '\0',
38
4
            u8: 0,
39
4
            u16: 0,
40
4
            u32: 0,
41
4
            u64: 0,
42
4
            u128: 0,
43
4
            usize: 0,
44
4
            i8: i8::MIN,
45
4
            i16: i16::MIN,
46
4
            i32: i32::MIN,
47
4
            i64: i64::MIN,
48
4
            i128: i128::from(i64::MIN), /* To make deserialization strings consistent and compatible across feature flags */
49
4
            isize: isize::MIN,
50
4
            bool: false,
51
4
        }
52
4
    }
53

            
54
4
    fn max() -> Self {
55
4
        Self {
56
4
            str: Cow::Borrowed("hello \u{1_F980}"),
57
4
            bytes: serde_bytes::ByteBuf::from(b"hello, world".to_vec()),
58
4
            char: '\u{1_F980}',
59
4
            u8: u8::MAX,
60
4
            u16: u16::MAX,
61
4
            u32: u32::MAX,
62
4
            u64: u64::MAX,
63
4
            u128: u128::from(u64::MAX), /* To make deserialization strings consistent and compatible across feature flags */
64
4
            usize: usize::MAX,
65
4
            i8: i8::MAX,
66
4
            i16: i16::MAX,
67
4
            i32: i32::MAX,
68
4
            i64: i64::MAX,
69
4
            i128: i128::from(i64::MAX), /* To make deserialization strings consistent and compatible across feature flags */
70
4
            isize: isize::MAX,
71
4
            bool: true,
72
4
        }
73
4
    }
74
}
75

            
76
#[track_caller]
77
3
fn roundtrip<T: Debug + Serialize + for<'de> Deserialize<'de> + PartialEq>(value: &T, check: &str) {
78
3
    let rendered = dbg!(crate::to_string(value).expect("no errors"));
79
3
    assert_eq!(rendered, check);
80
3
    let restored: T = crate::from_str(&rendered).expect("deserialization failed");
81
3
    assert_eq!(&restored, value);
82
3
}
83

            
84
#[track_caller]
85
3
fn roundtrip_pretty<T: Debug + Serialize + for<'de> Deserialize<'de> + PartialEq>(
86
3
    value: &T,
87
3
    check: &str,
88
3
) {
89
3
    let rendered = crate::to_string_pretty(value).expect("no errors");
90
3
    println!("{rendered}");
91
3
    assert_eq!(rendered, check);
92
3
    let restored: T = crate::from_str(&rendered).expect("deserialization failed");
93
3
    assert_eq!(&restored, value);
94
3
}
95

            
96
#[track_caller]
97
4
fn roundtrip_implicit_map<T: Debug + Serialize + for<'de> Deserialize<'de> + PartialEq>(
98
4
    value: &T,
99
4
    check: &str,
100
4
) {
101
4
    let rendered = crate::ser::Config::pretty()
102
4
        .implicit_map_at_root(true)
103
4
        .serialize(value)
104
4
        .expect("no errors");
105
4
    println!("{rendered}");
106
4
    assert_eq!(rendered, check);
107
4
    let restored: T = crate::parser::Config::default()
108
4
        .allow_implicit_map_at_root(true)
109
4
        .deserialize(&rendered)
110
4
        .expect("deserialization failed");
111
4
    assert_eq!(&restored, value);
112
4
}
113

            
114
#[track_caller]
115
3
fn roundtrip_anonymous_structs<T: Debug + Serialize + for<'de> Deserialize<'de> + PartialEq>(
116
3
    value: &T,
117
3
    check: &str,
118
3
) {
119
3
    let rendered = crate::ser::Config::new()
120
3
        .anonymous_structs(true)
121
3
        .serialize(value)
122
3
        .expect("no errors");
123
3
    println!("{rendered}");
124
3
    assert_eq!(rendered, check);
125
3
    let restored: T = crate::parser::Config::default()
126
3
        .allow_implicit_map_at_root(true)
127
3
        .deserialize(&rendered)
128
3
        .expect("deserialization failed");
129
3
    assert_eq!(&restored, value);
130
3
}
131

            
132
#[test]
133
1
fn struct_of_everything() {
134
1
    roundtrip(&StructOfEverything::default(), "StructOfEverything{str:\"\",bytes:b\"\",char:'\\0',u8:0,u16:0,u32:0,u64:0,u128:0,usize:0,i8:0,i16:0,i32:0,i64:0,i128:0,isize:0,bool:false}");
135
1
    roundtrip(&StructOfEverything::min(), "StructOfEverything{str:\"\\0\",bytes:b\"\\0\",char:'\\0',u8:0,u16:0,u32:0,u64:0,u128:0,usize:0,i8:-128,i16:-32768,i32:-2147483648,i64:-9223372036854775808,i128:-9223372036854775808,isize:-9223372036854775808,bool:false}");
136
1
    roundtrip(&StructOfEverything::max(), "StructOfEverything{str:\"hello 🦀\",bytes:b\"hello, world\",char:'🦀',u8:255,u16:65535,u32:4294967295,u64:18446744073709551615,u128:18446744073709551615,usize:18446744073709551615,i8:127,i16:32767,i32:2147483647,i64:9223372036854775807,i128:9223372036854775807,isize:9223372036854775807,bool:true}");
137
1
}
138

            
139
#[test]
140
1
fn struct_of_everything_pretty() {
141
1
    roundtrip_pretty(&StructOfEverything::default(), "StructOfEverything {\n  str: \"\",\n  bytes: b\"\",\n  char: '\\0',\n  u8: 0,\n  u16: 0,\n  u32: 0,\n  u64: 0,\n  u128: 0,\n  usize: 0,\n  i8: 0,\n  i16: 0,\n  i32: 0,\n  i64: 0,\n  i128: 0,\n  isize: 0,\n  bool: false\n}");
142
1
    roundtrip_pretty(&StructOfEverything::min(), "StructOfEverything {\n  str: \"\\0\",\n  bytes: b\"\\0\",\n  char: '\\0',\n  u8: 0,\n  u16: 0,\n  u32: 0,\n  u64: 0,\n  u128: 0,\n  usize: 0,\n  i8: -128,\n  i16: -32768,\n  i32: -2147483648,\n  i64: -9223372036854775808,\n  i128: -9223372036854775808,\n  isize: -9223372036854775808,\n  bool: false\n}");
143
1
    roundtrip_pretty(&StructOfEverything::max(), "StructOfEverything {\n  str: \"hello 🦀\",\n  bytes: b\"hello, world\",\n  char: '🦀',\n  u8: 255,\n  u16: 65535,\n  u32: 4294967295,\n  u64: 18446744073709551615,\n  u128: 18446744073709551615,\n  usize: 18446744073709551615,\n  i8: 127,\n  i16: 32767,\n  i32: 2147483647,\n  i64: 9223372036854775807,\n  i128: 9223372036854775807,\n  isize: 9223372036854775807,\n  bool: true\n}");
144
1
}
145

            
146
#[test]
147
1
fn struct_of_everything_implicit() {
148
1
    roundtrip_implicit_map(&StructOfEverything::default(), "str: \"\"\nbytes: b\"\"\nchar: '\\0'\nu8: 0\nu16: 0\nu32: 0\nu64: 0\nu128: 0\nusize: 0\ni8: 0\ni16: 0\ni32: 0\ni64: 0\ni128: 0\nisize: 0\nbool: false\n");
149
1
    roundtrip_implicit_map(&StructOfEverything::min(), "str: \"\\0\"\nbytes: b\"\\0\"\nchar: '\\0'\nu8: 0\nu16: 0\nu32: 0\nu64: 0\nu128: 0\nusize: 0\ni8: -128\ni16: -32768\ni32: -2147483648\ni64: -9223372036854775808\ni128: -9223372036854775808\nisize: -9223372036854775808\nbool: false\n");
150
1
    roundtrip_implicit_map(&StructOfEverything::max(), "str: \"hello 🦀\"\nbytes: b\"hello, world\"\nchar: '🦀'\nu8: 255\nu16: 65535\nu32: 4294967295\nu64: 18446744073709551615\nu128: 18446744073709551615\nusize: 18446744073709551615\ni8: 127\ni16: 32767\ni32: 2147483647\ni64: 9223372036854775807\ni128: 9223372036854775807\nisize: 9223372036854775807\nbool: true\n");
151
1
}
152

            
153
#[test]
154
1
fn struct_of_everything_anonymous() {
155
1
    roundtrip_anonymous_structs(&StructOfEverything::default(), "{str:\"\",bytes:b\"\",char:'\\0',u8:0,u16:0,u32:0,u64:0,u128:0,usize:0,i8:0,i16:0,i32:0,i64:0,i128:0,isize:0,bool:false}");
156
1
    roundtrip_anonymous_structs(&StructOfEverything::min(), "{str:\"\\0\",bytes:b\"\\0\",char:'\\0',u8:0,u16:0,u32:0,u64:0,u128:0,usize:0,i8:-128,i16:-32768,i32:-2147483648,i64:-9223372036854775808,i128:-9223372036854775808,isize:-9223372036854775808,bool:false}");
157
1
    roundtrip_anonymous_structs(&StructOfEverything::max(), "{str:\"hello 🦀\",bytes:b\"hello, world\",char:'🦀',u8:255,u16:65535,u32:4294967295,u64:18446744073709551615,u128:18446744073709551615,usize:18446744073709551615,i8:127,i16:32767,i32:2147483647,i64:9223372036854775807,i128:9223372036854775807,isize:9223372036854775807,bool:true}");
158
1
}
159

            
160
#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)]
161
#[serde(untagged)]
162
enum UntaggedEnum {
163
    Simple(SimpleStruct),
164
    NewtypeBool(NewtypeBool),
165
    Unit(UnitStruct),
166
}
167

            
168
19
#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)]
169
enum TaggedEnum {
170
    Tuple(bool, bool),
171
    Struct { a: u64 },
172
    NewtypeStruct(SimpleStruct),
173
    NewtypeTuple(SimpleTuple),
174
    NewtypeBool(bool),
175
    Unit,
176
}
177

            
178
8
#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)]
179
struct SimpleStruct {
180
    a: u64,
181
}
182

            
183
2
#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)]
184
struct SimpleTuple(u64, bool);
185

            
186
5
#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)]
187
struct NewtypeBool(bool);
188

            
189
2
#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)]
190
struct UnitStruct;
191

            
192
#[test]
193
1
fn deserialize_any() {
194
1
    let untagged: UntaggedEnum = crate::from_str("()").unwrap();
195
1
    assert_eq!(untagged, UntaggedEnum::Unit(UnitStruct));
196
1
    let untagged: UntaggedEnum = crate::from_str("true").unwrap();
197
1
    assert_eq!(untagged, UntaggedEnum::NewtypeBool(NewtypeBool(true)));
198

            
199
1
    let untagged: UntaggedEnum = crate::from_str("{a:0}").unwrap();
200
1
    assert_eq!(untagged, UntaggedEnum::Simple(SimpleStruct { a: 0 }));
201
    // Serde doesn't support tagged in an untagged context, which makes sense
202
    // given what it's named. We can't pass the C to the visitor without causing
203
    // an error within deserialize_any() or causing it to think we're
204
    // deserializing only a string.
205
1
    let untagged: UntaggedEnum = crate::from_str("C{a:0}").unwrap();
206
1
    assert_eq!(untagged, UntaggedEnum::Simple(SimpleStruct { a: 0 }));
207

            
208
    // Some and None are special cases
209
1
    let untagged: Option<UntaggedEnum> = crate::from_str("None").unwrap();
210
1
    assert_eq!(untagged, None);
211
1
    let untagged: Option<UntaggedEnum> = crate::from_str("Some(())").unwrap();
212
1
    assert_eq!(untagged, Some(UntaggedEnum::Unit(UnitStruct)));
213
1
}
214

            
215
#[test]
216
1
fn deserialize_tagged() {
217
1
    let tagged: TaggedEnum = crate::from_str("Tuple (true, false)").unwrap();
218
1
    assert_eq!(tagged, TaggedEnum::Tuple(true, false));
219
1
    let tagged: TaggedEnum = crate::from_str("Struct {a: 1}").unwrap();
220
1
    assert_eq!(tagged, TaggedEnum::Struct { a: 1 });
221

            
222
1
    let tagged: TaggedEnum = crate::from_str("NewtypeStruct {a: 1}").unwrap();
223
1
    assert_eq!(tagged, TaggedEnum::NewtypeStruct(SimpleStruct { a: 1 }));
224
1
    let tagged: TaggedEnum = crate::from_str("NewtypeStruct({a: 1})").unwrap();
225
1
    assert_eq!(tagged, TaggedEnum::NewtypeStruct(SimpleStruct { a: 1 }));
226
1
    let tagged: TaggedEnum = crate::from_str("NewtypeTuple(1, false)").unwrap();
227
1
    assert_eq!(tagged, TaggedEnum::NewtypeTuple(SimpleTuple(1, false)));
228
1
    let tagged: TaggedEnum = crate::from_str("NewtypeTuple((1, false))").unwrap();
229
1
    assert_eq!(tagged, TaggedEnum::NewtypeTuple(SimpleTuple(1, false)));
230
1
    let tagged: TaggedEnum = crate::from_str("NewtypeBool(true)").unwrap();
231
1
    assert_eq!(tagged, TaggedEnum::NewtypeBool(true));
232
1
    let tagged: TaggedEnum = crate::from_str("Unit").unwrap();
233
1
    assert_eq!(tagged, TaggedEnum::Unit);
234
1
}
235

            
236
#[test]
237
1
fn value_from_serialize() {
238
1
    let original = StructOfEverything::default();
239
1
    let value = dbg!(Value::from_serialize(&original).unwrap());
240
1
    let from_value: StructOfEverything = value.to_deserialize().unwrap();
241
1
    assert_eq!(original, from_value);
242
1
}
243

            
244
#[test]
245
1
fn implicit_btree_map() {
246
1
    roundtrip_implicit_map(
247
1
        &BTreeMap::from([(String::from("Hello"), 1), (String::from("World"), 2)]),
248
1
        "\"Hello\": 1\n\"World\": 2\n",
249
1
    );
250
1
}