1
use serde::{Deserialize, Serialize};
2

            
3
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
4
enum InnerEnum {
5
    Unit,
6
    Newtype(bool),
7
    Tuple(bool, i32),
8
    Struct { field: char },
9
}
10

            
11
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
12
#[serde(deny_unknown_fields)]
13
struct Container {
14
    field: InnerEnum,
15
}
16

            
17
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
18
enum OuterEnum {
19
    Variant(Container),
20
    Sum { field: InnerEnum, value: i32 },
21
}
22

            
23
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
24
#[serde(tag = "tag")]
25
enum OuterEnumInternal {
26
    Variant(Container),
27
    Sum { field: InnerEnum, value: i32 },
28
}
29

            
30
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
31
#[serde(tag = "tag", content = "c")]
32
enum OuterEnumAdjacent {
33
    Variant(Container),
34
    Sum { field: InnerEnum, value: i32 },
35
}
36

            
37
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
38
#[serde(untagged)]
39
enum OuterEnumUntagged {
40
    Variant(Container),
41
    Sum { field: InnerEnum, value: i32 },
42
}
43

            
44
#[test]
45
4
fn test_enum_in_enum_roundtrip() {
46
4
    let outer = OuterEnum::Variant(Container {
47
4
        field: InnerEnum::Unit,
48
4
    });
49

            
50
4
    let ron = ron::to_string(&outer).unwrap();
51

            
52
4
    assert_eq!(ron, "Variant((field:Unit))");
53

            
54
4
    let de = ron::from_str::<OuterEnum>(&ron);
55

            
56
4
    assert_eq!(de, Ok(outer));
57

            
58
4
    let outer = OuterEnum::Sum {
59
4
        field: InnerEnum::Newtype(true),
60
4
        value: 42,
61
4
    };
62

            
63
4
    let ron = ron::to_string(&outer).unwrap();
64

            
65
4
    assert_eq!(ron, "Sum(field:Newtype(true),value:42)");
66

            
67
4
    let de = ron::from_str::<OuterEnum>(&ron);
68

            
69
4
    assert_eq!(de, Ok(outer));
70

            
71
4
    let outer = OuterEnum::Sum {
72
4
        field: InnerEnum::Tuple(true, 24),
73
4
        value: 42,
74
4
    };
75

            
76
4
    let ron = ron::to_string(&outer).unwrap();
77

            
78
4
    assert_eq!(ron, "Sum(field:Tuple(true,24),value:42)");
79

            
80
4
    let de = ron::from_str::<OuterEnum>(&ron);
81

            
82
4
    assert_eq!(de, Ok(outer));
83

            
84
4
    let outer = OuterEnum::Sum {
85
4
        field: InnerEnum::Struct { field: '🦀' },
86
4
        value: 42,
87
4
    };
88

            
89
4
    let ron = ron::to_string(&outer).unwrap();
90

            
91
4
    assert_eq!(ron, "Sum(field:Struct(field:'🦀'),value:42)");
92

            
93
4
    let de = ron::from_str::<OuterEnum>(&ron);
94

            
95
4
    assert_eq!(de, Ok(outer));
96
4
}
97

            
98
#[test]
99
4
fn test_enum_in_internally_tagged_roundtrip() {
100
4
    let outer = OuterEnumInternal::Variant(Container {
101
4
        field: InnerEnum::Unit,
102
4
    });
103

            
104
4
    let ron = ron::to_string(&outer).unwrap();
105

            
106
4
    assert_eq!(ron, "(tag:\"Variant\",field:Unit)");
107

            
108
4
    let de = ron::from_str::<OuterEnumInternal>(&ron);
109

            
110
4
    assert_eq!(de, Ok(outer));
111

            
112
4
    let outer = OuterEnumInternal::Sum {
113
4
        field: InnerEnum::Newtype(true),
114
4
        value: 42,
115
4
    };
116

            
117
4
    let ron = ron::to_string(&outer).unwrap();
118

            
119
4
    assert_eq!(ron, "(tag:\"Sum\",field:Newtype(true),value:42)");
120

            
121
4
    let de = ron::from_str::<OuterEnumInternal>(&ron);
122

            
123
4
    assert_eq!(de, Ok(outer));
124

            
125
4
    let outer = OuterEnumInternal::Sum {
126
4
        field: InnerEnum::Tuple(true, 24),
127
4
        value: 42,
128
4
    };
129

            
130
4
    let ron = ron::to_string(&outer).unwrap();
131

            
132
4
    assert_eq!(ron, "(tag:\"Sum\",field:Tuple(true,24),value:42)");
133

            
134
4
    let de = ron::from_str::<OuterEnumInternal>(&ron);
135

            
136
4
    assert_eq!(de, Ok(outer));
137

            
138
4
    let outer = OuterEnumInternal::Sum {
139
4
        field: InnerEnum::Struct { field: '🦀' },
140
4
        value: 42,
141
4
    };
142

            
143
4
    let ron = ron::to_string(&outer).unwrap();
144

            
145
4
    assert_eq!(ron, "(tag:\"Sum\",field:Struct(field:'🦀'),value:42)");
146

            
147
4
    let de = ron::from_str::<OuterEnumInternal>(&ron);
148

            
149
4
    assert_eq!(de, Ok(outer));
150
4
}
151

            
152
#[test]
153
4
fn test_enum_in_adjacently_tagged_roundtrip() {
154
4
    let outer = OuterEnumAdjacent::Variant(Container {
155
4
        field: InnerEnum::Unit,
156
4
    });
157

            
158
4
    let ron = ron::to_string(&outer).unwrap();
159

            
160
4
    assert_eq!(ron, "(tag:Variant,c:(field:Unit))");
161

            
162
4
    let de = ron::from_str::<OuterEnumAdjacent>(&ron);
163

            
164
4
    assert_eq!(de, Ok(outer));
165

            
166
4
    let outer = OuterEnumAdjacent::Sum {
167
4
        field: InnerEnum::Newtype(true),
168
4
        value: 42,
169
4
    };
170

            
171
4
    let ron = ron::to_string(&outer).unwrap();
172

            
173
4
    assert_eq!(ron, "(tag:Sum,c:(field:Newtype(true),value:42))");
174

            
175
4
    let de = ron::from_str::<OuterEnumAdjacent>(&ron);
176

            
177
4
    assert_eq!(de, Ok(outer));
178

            
179
4
    let outer = OuterEnumAdjacent::Sum {
180
4
        field: InnerEnum::Tuple(true, 24),
181
4
        value: 42,
182
4
    };
183

            
184
4
    let ron = ron::to_string(&outer).unwrap();
185

            
186
4
    assert_eq!(ron, "(tag:Sum,c:(field:Tuple(true,24),value:42))");
187

            
188
4
    let de = ron::from_str::<OuterEnumAdjacent>(&ron);
189

            
190
4
    assert_eq!(de, Ok(outer));
191

            
192
4
    let outer = OuterEnumAdjacent::Sum {
193
4
        field: InnerEnum::Struct { field: '🦀' },
194
4
        value: 42,
195
4
    };
196

            
197
4
    let ron = ron::to_string(&outer).unwrap();
198

            
199
4
    assert_eq!(ron, "(tag:Sum,c:(field:Struct(field:'🦀'),value:42))");
200

            
201
4
    let de = ron::from_str::<OuterEnumAdjacent>(&ron);
202

            
203
4
    assert_eq!(de, Ok(outer));
204
4
}
205

            
206
#[test]
207
4
fn test_enum_in_untagged_roundtrip() {
208
4
    let outer = OuterEnumUntagged::Variant(Container {
209
4
        field: InnerEnum::Unit,
210
4
    });
211

            
212
4
    let ron = ron::to_string(&outer).unwrap();
213

            
214
4
    assert_eq!(ron, "(field:Unit)");
215

            
216
4
    let de = ron::from_str::<OuterEnumUntagged>(&ron);
217

            
218
4
    assert_eq!(de, Ok(outer));
219

            
220
4
    let outer = OuterEnumUntagged::Sum {
221
4
        field: InnerEnum::Newtype(true),
222
4
        value: 42,
223
4
    };
224

            
225
4
    let ron = ron::to_string(&outer).unwrap();
226

            
227
4
    assert_eq!(ron, "(field:Newtype(true),value:42)");
228

            
229
4
    let de = ron::from_str::<OuterEnumUntagged>(&ron);
230

            
231
4
    assert_eq!(de, Ok(outer));
232

            
233
4
    let outer = OuterEnumUntagged::Sum {
234
4
        field: InnerEnum::Tuple(true, 24),
235
4
        value: 42,
236
4
    };
237

            
238
4
    let ron = ron::to_string(&outer).unwrap();
239

            
240
4
    assert_eq!(ron, "(field:Tuple(true,24),value:42)");
241

            
242
4
    let de = ron::from_str::<OuterEnumUntagged>(&ron);
243

            
244
4
    assert_eq!(de, Ok(outer));
245

            
246
4
    let outer = OuterEnumUntagged::Sum {
247
4
        field: InnerEnum::Struct { field: '🦀' },
248
4
        value: 42,
249
4
    };
250

            
251
4
    let ron = ron::to_string(&outer).unwrap();
252

            
253
4
    assert_eq!(ron, "(field:Struct(field:'🦀'),value:42)");
254

            
255
4
    let de = ron::from_str::<OuterEnumUntagged>(&ron);
256

            
257
4
    assert_eq!(de, Ok(outer));
258
4
}