1
use std::collections::{BTreeMap, HashMap};
2

            
3
use ron::{error::Position, error::SpannedError, extensions::Extensions, ser::PrettyConfig, Error};
4
use serde::{Deserialize, Serialize};
5

            
6
#[test]
7
4
fn struct_names_inside_internally_tagged() {
8
16
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
9
    struct A {
10
        hi: i32,
11
    }
12

            
13
32
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
14
    #[serde(tag = "tag")]
15
    enum InternallyTagged {
16
        B { ho: i32, a: A },
17
    }
18

            
19
4
    assert_eq!(
20
4
        check_roundtrip(
21
4
            &InternallyTagged::B {
22
4
                ho: 24,
23
4
                a: A { hi: 42 }
24
4
            },
25
4
            PrettyConfig::default()
26
4
        ),
27
4
        Ok(())
28
4
    );
29
4
    assert_eq!(
30
4
        check_roundtrip(
31
4
            &InternallyTagged::B {
32
4
                ho: 24,
33
4
                a: A { hi: 42 }
34
4
            },
35
4
            PrettyConfig::default().struct_names(true)
36
4
        ),
37
4
        Err(Err(SpannedError {
38
4
            code: Error::MissingStructField {
39
4
                field: "hi",
40
4
                outer: None
41
4
            },
42
4
            position: Position { line: 7, col: 2 }
43
4
        })),
44
4
    );
45
4
}
46

            
47
#[test]
48
4
fn struct_names_inside_adjacently_tagged() {
49
24
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
50
    struct A {
51
        hi: i32,
52
    }
53

            
54
88
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
55
    #[serde(tag = "tag", content = "content")]
56
    enum AdjacentlyTagged {
57
        B { ho: i32, a: A },
58
    }
59

            
60
4
    assert_eq!(
61
4
        check_roundtrip(
62
4
            &AdjacentlyTagged::B {
63
4
                ho: 24,
64
4
                a: A { hi: 42 }
65
4
            },
66
4
            PrettyConfig::default()
67
4
        ),
68
4
        Ok(())
69
4
    );
70
4
    assert_eq!(
71
4
        check_roundtrip(
72
4
            &AdjacentlyTagged::B {
73
4
                ho: 24,
74
4
                a: A { hi: 42 }
75
4
            },
76
4
            PrettyConfig::default().struct_names(true)
77
4
        ),
78
4
        Ok(()),
79
4
    );
80
4
    assert_eq!(
81
4
        ron::from_str::<AdjacentlyTagged>(
82
4
            "AdjacentlyTagged(tag: B, content: B(ho: 24, a: A(hi: 42)))"
83
4
        ),
84
4
        Ok(AdjacentlyTagged::B {
85
4
            ho: 24,
86
4
            a: A { hi: 42 }
87
4
        }),
88
4
    );
89
4
    assert_eq!(
90
4
        ron::from_str::<AdjacentlyTagged>(
91
4
            "AdjacentlyTagged(content: B(ho: 24, a: A(hi: 42)), tag: B)"
92
4
        ),
93
4
        Err(SpannedError {
94
4
            code: Error::MissingStructField {
95
4
                field: "ho",
96
4
                outer: Some(String::from("AdjacentlyTagged"))
97
4
            },
98
4
            position: Position { line: 1, col: 58 }
99
4
        }),
100
4
    );
101
4
}
102

            
103
#[test]
104
4
fn struct_names_inside_untagged() {
105
8
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
106
    struct A {
107
        hi: i32,
108
    }
109

            
110
20
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
111
    #[serde(untagged)]
112
    enum Untagged {
113
        B { ho: i32, a: A },
114
    }
115

            
116
4
    assert_eq!(
117
4
        check_roundtrip(
118
4
            &Untagged::B {
119
4
                ho: 24,
120
4
                a: A { hi: 42 }
121
4
            },
122
4
            PrettyConfig::default()
123
4
        ),
124
4
        Ok(())
125
4
    );
126
4
    assert_eq!(
127
4
        check_roundtrip(
128
4
            &Untagged::B {
129
4
                ho: 24,
130
4
                a: A { hi: 42 }
131
4
            },
132
4
            PrettyConfig::default().struct_names(true)
133
4
        ),
134
4
        Err(Err(SpannedError {
135
4
            code: Error::Message(String::from(
136
4
                "data did not match any variant of untagged enum Untagged"
137
4
            )),
138
4
            position: Position { line: 6, col: 2 }
139
4
        })),
140
4
    );
141
4
}
142

            
143
#[test]
144
4
fn struct_names_inside_flatten_struct() {
145
16
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
146
    struct A {
147
        hi: i32,
148
    }
149

            
150
20
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
151
    struct B {
152
        a: A,
153
    }
154

            
155
24
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
156
    struct FlattenedStruct {
157
        ho: i32,
158
        #[serde(flatten)]
159
        a: B,
160
    }
161

            
162
4
    assert_eq!(
163
4
        check_roundtrip(
164
4
            &FlattenedStruct {
165
4
                ho: 24,
166
4
                a: B { a: A { hi: 42 } }
167
4
            },
168
4
            PrettyConfig::default()
169
4
        ),
170
4
        Ok(())
171
4
    );
172
4
    assert_eq!(
173
4
        check_roundtrip(
174
4
            &FlattenedStruct {
175
4
                ho: 24,
176
4
                a: B { a: A { hi: 42 } }
177
4
            },
178
4
            PrettyConfig::default().struct_names(true)
179
4
        ),
180
4
        Err(Err(SpannedError {
181
4
            code: Error::MissingStructField {
182
4
                field: "hi",
183
4
                outer: None
184
4
            },
185
4
            position: Position { line: 6, col: 1 }
186
4
        })),
187
4
    );
188
4
}
189

            
190
#[test]
191
4
fn struct_names_inside_flatten_struct_variant() {
192
16
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
193
    struct A {
194
        hi: i32,
195
    }
196

            
197
20
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
198
    struct B {
199
        a: A,
200
    }
201

            
202
40
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
203
    enum FlattenedStructVariant {
204
        C {
205
            ho: i32,
206
            #[serde(flatten)]
207
            a: B,
208
        },
209
    }
210

            
211
4
    assert_eq!(
212
4
        check_roundtrip(
213
4
            &FlattenedStructVariant::C {
214
4
                ho: 24,
215
4
                a: B { a: A { hi: 42 } }
216
4
            },
217
4
            PrettyConfig::default()
218
4
        ),
219
4
        Ok(())
220
4
    );
221
4
    assert_eq!(
222
4
        check_roundtrip(
223
4
            &FlattenedStructVariant::C {
224
4
                ho: 24,
225
4
                a: B { a: A { hi: 42 } }
226
4
            },
227
4
            PrettyConfig::default().struct_names(true)
228
4
        ),
229
4
        Err(Err(SpannedError {
230
4
            code: Error::MissingStructField {
231
4
                field: "hi",
232
4
                outer: Some(String::from("C"))
233
4
            },
234
4
            position: Position { line: 6, col: 1 }
235
4
        })),
236
4
    );
237
4
}
238

            
239
#[test]
240
4
fn implicit_some_inside_internally_tagged() {
241
16
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
242
    struct A {
243
        hi: Option<Option<()>>,
244
    }
245

            
246
32
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
247
    #[serde(tag = "tag")]
248
    enum InternallyTagged {
249
        B { ho: i32, a: A },
250
    }
251

            
252
4
    assert_eq!(
253
4
        check_roundtrip(
254
4
            &InternallyTagged::B {
255
4
                ho: 24,
256
4
                a: A { hi: Some(Some(())) }
257
4
            },
258
4
            PrettyConfig::default()
259
4
        ),
260
4
        Ok(())
261
4
    );
262
4
    assert_eq!(
263
4
        check_roundtrip(
264
4
            &InternallyTagged::B {
265
4
                ho: 24,
266
4
                a: A { hi: Some(Some(())) }
267
4
            },
268
4
            PrettyConfig::default().extensions(Extensions::IMPLICIT_SOME)
269
4
        ),
270
4
        Err(Ok(Error::Message(String::from("ROUNDTRIP error: B { ho: 24, a: A { hi: Some(Some(())) } } != B { ho: 24, a: A { hi: None } }"))))
271
4
    );
272
4
}
273

            
274
#[test]
275
4
fn implicit_some_inside_adjacently_tagged() {
276
12
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
277
    struct Unit;
278

            
279
32
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
280
    struct A {
281
        hi: Option<Option<Unit>>,
282
    }
283

            
284
92
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
285
    #[serde(tag = "tag", content = "content")]
286
    enum AdjacentlyTagged {
287
        B { ho: i32, a: A },
288
    }
289

            
290
4
    assert_eq!(
291
4
        check_roundtrip(
292
4
            &AdjacentlyTagged::B {
293
4
                ho: 24,
294
4
                a: A {
295
4
                    hi: Some(Some(Unit))
296
4
                }
297
4
            },
298
4
            PrettyConfig::default()
299
4
        ),
300
4
        Ok(())
301
4
    );
302
4
    assert_eq!(
303
4
        check_roundtrip(
304
4
            &AdjacentlyTagged::B {
305
4
                ho: 24,
306
4
                a: A {
307
4
                    hi: Some(Some(Unit))
308
4
                }
309
4
            },
310
4
            PrettyConfig::default().extensions(Extensions::IMPLICIT_SOME)
311
4
        ),
312
4
        Ok(()),
313
4
    );
314
4
    assert_eq!(
315
4
        ron::from_str::<AdjacentlyTagged>(
316
4
            "#![enable(implicit_some)] (tag: B, content: (ho: 24, a: A(hi: ())))"
317
4
        ),
318
4
        Ok(AdjacentlyTagged::B {
319
4
            ho: 24,
320
4
            a: A {
321
4
                hi: Some(Some(Unit))
322
4
            }
323
4
        }),
324
4
    );
325
4
    assert_eq!(
326
4
        ron::from_str::<AdjacentlyTagged>(
327
4
            "#![enable(implicit_some)] (content: (ho: 24, a: A(hi: ())), tag: B)"
328
4
        ),
329
4
        Ok(AdjacentlyTagged::B {
330
4
            ho: 24,
331
4
            a: A { hi: None } // THIS IS WRONG
332
4
        }),
333
4
    );
334
4
}
335

            
336
#[test]
337
4
fn implicit_some_inside_untagged() {
338
16
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
339
    struct A {
340
        hi: Option<Option<()>>,
341
    }
342

            
343
24
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
344
    #[serde(untagged)]
345
    enum Untagged {
346
        B { ho: i32, a: A },
347
    }
348

            
349
4
    assert_eq!(
350
4
        check_roundtrip(
351
4
            &Untagged::B {
352
4
                ho: 24,
353
4
                a: A { hi: Some(Some(())) }
354
4
            },
355
4
            PrettyConfig::default()
356
4
        ),
357
4
        Ok(())
358
4
    );
359
4
    assert_eq!(
360
4
        check_roundtrip(
361
4
            &Untagged::B {
362
4
                ho: 24,
363
4
                a: A { hi: Some(Some(())) }
364
4
            },
365
4
            PrettyConfig::default().extensions(Extensions::IMPLICIT_SOME)
366
4
        ),
367
4
        Err(Ok(Error::Message(String::from(
368
4
            "ROUNDTRIP error: B { ho: 24, a: A { hi: Some(Some(())) } } != B { ho: 24, a: A { hi: None } }"
369
4
        )))),
370
4
    );
371
4
}
372

            
373
#[test]
374
4
fn implicit_some_inside_flatten_struct() {
375
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
376
    #[serde(untagged)]
377
    enum Untagged {
378
        Unit,
379
    }
380

            
381
16
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
382
    struct A {
383
        hi: Option<Option<Untagged>>,
384
    }
385

            
386
16
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
387
    struct B {
388
        a: A,
389
    }
390

            
391
24
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
392
    struct FlattenedStruct {
393
        ho: i32,
394
        #[serde(flatten)]
395
        a: B,
396
    }
397

            
398
4
    assert_eq!(
399
4
        check_roundtrip(
400
4
            &FlattenedStruct {
401
4
                ho: 24,
402
4
                a: B {
403
4
                    a: A {
404
4
                        hi: Some(Some(Untagged::Unit))
405
4
                    }
406
4
                }
407
4
            },
408
4
            PrettyConfig::default()
409
4
        ),
410
4
        Ok(())
411
4
    );
412
4
    assert_eq!(
413
4
        check_roundtrip(
414
4
            &FlattenedStruct {
415
4
                ho: 24,
416
4
                a: B {
417
4
                    a: A { hi: Some(Some(Untagged::Unit)) }
418
4
                }
419
4
            },
420
4
            PrettyConfig::default().extensions(Extensions::IMPLICIT_SOME)
421
4
        ),
422
4
        Err(Ok(Error::Message(String::from("ROUNDTRIP error: FlattenedStruct { ho: 24, a: B { a: A { hi: Some(Some(Unit)) } } } != FlattenedStruct { ho: 24, a: B { a: A { hi: None } } }"))))
423
4
    );
424
4
}
425

            
426
#[test]
427
4
fn implicit_some_inside_flatten_struct_variant() {
428
20
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
429
    struct A {
430
        hi: Option<Option<[u8; 0]>>,
431
    }
432

            
433
20
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
434
    struct B {
435
        a: A,
436
    }
437

            
438
40
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
439
    enum FlattenedStructVariant {
440
        C {
441
            ho: i32,
442
            #[serde(flatten)]
443
            a: B,
444
        },
445
    }
446

            
447
4
    assert_eq!(
448
4
        check_roundtrip(
449
4
            &FlattenedStructVariant::C {
450
4
                ho: 24,
451
4
                a: B {
452
4
                    a: A { hi: Some(Some([])) }
453
4
                }
454
4
            },
455
4
            PrettyConfig::default()
456
4
        ),
457
4
        Err(Err(SpannedError {
458
4
            code: Error::InvalidValueForType {
459
4
                expected: String::from("an empty array"),
460
4
                found: String::from("a unit value")
461
4
            },
462
4
            position: Position { line: 6, col: 1 }
463
4
        }))
464
4
    );
465
4
    assert_eq!(
466
4
        check_roundtrip(
467
4
            &FlattenedStructVariant::C {
468
4
                ho: 24,
469
4
                a: B {
470
4
                    a: A { hi: Some(Some([])) }
471
4
                }
472
4
            },
473
4
            PrettyConfig::default().extensions(Extensions::IMPLICIT_SOME)
474
4
        ),
475
4
        Err(Ok(Error::Message(String::from("ROUNDTRIP error: C { ho: 24, a: B { a: A { hi: Some(Some([])) } } } != C { ho: 24, a: B { a: A { hi: None } } }"))))
476
4
    );
477
4
}
478

            
479
#[test]
480
4
fn newtype_inside_internally_tagged() {
481
8
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
482
    struct A(i32);
483

            
484
16
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
485
    #[serde(tag = "tag")]
486
    enum InternallyTagged {
487
        B { ho: i32, a: A },
488
    }
489

            
490
    // NOTE:
491
    // 1. ron is correctly collected into Content, newtype is a one-seq here
492
    // 2. newtype asks ContentDeserializer for newtype
493
    // 3. ContentDeserializer forwards any value to visit_newtype_struct
494
    //    https://github.com/serde-rs/serde/blob/8c4aad3a59515f7b779f764d5e16d6bae297ab7f/serde/src/private/de.rs#L1347-L1359
495

            
496
4
    assert_eq!(
497
4
        check_roundtrip(
498
4
            &InternallyTagged::B { ho: 24, a: A(42) },
499
4
            PrettyConfig::default()
500
4
        ),
501
4
        Err(Err(SpannedError {
502
4
            code: Error::InvalidValueForType {
503
4
                expected: String::from("i32"),
504
4
                found: String::from("a sequence")
505
4
            },
506
4
            position: Position { line: 5, col: 2 }
507
4
        }))
508
4
    );
509
4
}
510

            
511
#[test]
512
4
fn newtype_inside_adjacently_tagged() {
513
16
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
514
    struct A(i32);
515

            
516
68
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
517
    #[serde(tag = "tag", content = "content")]
518
    enum AdjacentlyTagged {
519
        B { ho: i32, a: A },
520
    }
521

            
522
4
    assert_eq!(
523
4
        check_roundtrip(
524
4
            &AdjacentlyTagged::B { ho: 24, a: A(42) },
525
4
            PrettyConfig::default()
526
4
        ),
527
4
        Ok(())
528
4
    );
529
4
    assert_eq!(
530
4
        ron::from_str::<AdjacentlyTagged>("(tag: B, content: (ho: 24, a: (42)))"),
531
4
        Ok(AdjacentlyTagged::B { ho: 24, a: A(42) }),
532
4
    );
533
4
    assert_eq!(
534
4
        ron::from_str::<AdjacentlyTagged>("(content: (ho: 24, a: (42)), tag: B)"),
535
4
        Err(SpannedError {
536
4
            code: Error::InvalidValueForType {
537
4
                expected: String::from("i32"),
538
4
                found: String::from("a sequence")
539
4
            },
540
4
            position: Position { line: 1, col: 36 }
541
4
        })
542
4
    );
543
4
}
544

            
545
#[test]
546
4
fn newtype_inside_untagged() {
547
8
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
548
    struct A(i32);
549

            
550
12
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
551
    #[serde(untagged)]
552
    enum Untagged {
553
        B { ho: i32, a: A },
554
    }
555

            
556
4
    assert_eq!(
557
4
        check_roundtrip(&Untagged::B { ho: 24, a: A(42) }, PrettyConfig::default()),
558
4
        Err(Err(SpannedError {
559
4
            code: Error::Message(String::from(
560
4
                "data did not match any variant of untagged enum Untagged"
561
4
            )),
562
4
            position: Position { line: 4, col: 2 }
563
4
        }))
564
4
    );
565
4
}
566

            
567
#[test]
568
4
fn newtype_inside_flatten_struct() {
569
8
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
570
    struct A(i32);
571

            
572
12
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
573
    struct B {
574
        a: A,
575
    }
576

            
577
12
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
578
    struct FlattenedStruct {
579
        ho: i32,
580
        #[serde(flatten)]
581
        a: B,
582
    }
583

            
584
4
    assert_eq!(
585
4
        check_roundtrip(
586
4
            &FlattenedStruct {
587
4
                ho: 24,
588
4
                a: B { a: A(42) }
589
4
            },
590
4
            PrettyConfig::default()
591
4
        ),
592
4
        Err(Err(SpannedError {
593
4
            code: Error::InvalidValueForType {
594
4
                expected: String::from("i32"),
595
4
                found: String::from("a sequence")
596
4
            },
597
4
            position: Position { line: 4, col: 1 }
598
4
        }))
599
4
    );
600
4
}
601

            
602
#[test]
603
4
fn newtype_inside_flatten_struct_variant() {
604
8
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
605
    struct A(i32);
606

            
607
12
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
608
    struct B {
609
        a: A,
610
    }
611

            
612
20
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
613
    enum FlattenedStructVariant {
614
        C {
615
            ho: i32,
616
            #[serde(flatten)]
617
            a: B,
618
        },
619
    }
620

            
621
4
    assert_eq!(
622
4
        check_roundtrip(
623
4
            &FlattenedStructVariant::C {
624
4
                ho: 24,
625
4
                a: B { a: A(42) }
626
4
            },
627
4
            PrettyConfig::default()
628
4
        ),
629
4
        Err(Err(SpannedError {
630
4
            code: Error::InvalidValueForType {
631
4
                expected: String::from("i32"),
632
4
                found: String::from("a sequence")
633
4
            },
634
4
            position: Position { line: 4, col: 1 }
635
4
        }))
636
4
    );
637
4
}
638

            
639
#[test]
640
4
fn one_tuple_inside_unwrapped_newtype_variant_inside_internally_tagged() {
641
16
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
642
    enum A {
643
        Newtype((i32,)),
644
    }
645

            
646
32
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
647
    #[serde(tag = "tag")]
648
    enum InternallyTagged {
649
        B { ho: i32, a: A },
650
    }
651

            
652
4
    assert_eq!(
653
4
        check_roundtrip(
654
4
            &InternallyTagged::B {
655
4
                ho: 24,
656
4
                a: A::Newtype((42,))
657
4
            },
658
4
            PrettyConfig::default()
659
4
        ),
660
4
        Ok(())
661
4
    );
662
4
    assert_eq!(
663
4
        check_roundtrip(
664
4
            &InternallyTagged::B {
665
4
                ho: 24,
666
4
                a: A::Newtype((42,))
667
4
            },
668
4
            PrettyConfig::default().extensions(Extensions::UNWRAP_VARIANT_NEWTYPES)
669
4
        ),
670
4
        Err(Err(SpannedError {
671
4
            code: Error::InvalidValueForType {
672
4
                expected: String::from("a tuple of size 1"),
673
4
                found: String::from("the unsigned integer `42`")
674
4
            },
675
4
            position: Position { line: 6, col: 2 }
676
4
        }))
677
4
    );
678
4
}
679

            
680
#[test]
681
4
fn one_tuple_inside_unwrapped_newtype_variant_inside_adjacently_tagged() {
682
32
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
683
    enum A {
684
        Newtype([i32; 1]),
685
    }
686

            
687
92
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
688
    #[serde(tag = "tag", content = "content")]
689
    enum AdjacentlyTagged {
690
        B { ho: i32, a: A },
691
    }
692

            
693
4
    assert_eq!(
694
4
        check_roundtrip(
695
4
            &AdjacentlyTagged::B {
696
4
                ho: 24,
697
4
                a: A::Newtype([42])
698
4
            },
699
4
            PrettyConfig::default()
700
4
        ),
701
4
        Ok(())
702
4
    );
703
4
    assert_eq!(
704
4
        check_roundtrip(
705
4
            &AdjacentlyTagged::B {
706
4
                ho: 24,
707
4
                a: A::Newtype([42])
708
4
            },
709
4
            PrettyConfig::default().extensions(Extensions::UNWRAP_VARIANT_NEWTYPES)
710
4
        ),
711
4
        Ok(())
712
4
    );
713
4
    assert_eq!(
714
4
        ron::from_str::<AdjacentlyTagged>(
715
4
            "#![enable(unwrap_variant_newtypes)] (tag: B, content: (ho: 24, a: Newtype(42)))"
716
4
        ),
717
4
        Ok(AdjacentlyTagged::B {
718
4
            ho: 24,
719
4
            a: A::Newtype([42])
720
4
        }),
721
4
    );
722
4
    assert_eq!(
723
4
        ron::from_str::<AdjacentlyTagged>(
724
4
            "#![enable(unwrap_variant_newtypes)] (content: (ho: 24, a: Newtype(42)), tag: B)"
725
4
        ),
726
4
        Err(SpannedError {
727
4
            code: Error::InvalidValueForType {
728
4
                expected: String::from("an array of length 1"),
729
4
                found: String::from("the unsigned integer `42`")
730
4
            },
731
4
            position: Position { line: 1, col: 79 }
732
4
        })
733
4
    );
734
4
}
735

            
736
#[test]
737
4
fn one_tuple_inside_unwrapped_newtype_variant_inside_untagged() {
738
4
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
739
    struct OneTuple(i32, #[serde(skip)] ());
740

            
741
24
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
742
    #[serde(untagged)]
743
    enum Untagged {
744
        B { ho: i32, a: Option<OneTuple> },
745
    }
746

            
747
4
    assert_eq!(
748
4
        check_roundtrip(
749
4
            &Untagged::B {
750
4
                ho: 24,
751
4
                a: Some(OneTuple(42, ()))
752
4
            },
753
4
            PrettyConfig::default()
754
4
        ),
755
4
        Ok(())
756
4
    );
757
4
    assert_eq!(
758
4
        check_roundtrip(
759
4
            &Untagged::B {
760
4
                ho: 24,
761
4
                a: Some(OneTuple(42, ()))
762
4
            },
763
4
            PrettyConfig::default().extensions(Extensions::UNWRAP_VARIANT_NEWTYPES)
764
4
        ),
765
4
        Err(Err(SpannedError {
766
4
            code: Error::Message(String::from(
767
4
                "data did not match any variant of untagged enum Untagged"
768
4
            )),
769
4
            position: Position { line: 5, col: 2 }
770
4
        }))
771
4
    );
772
4
}
773

            
774
#[test]
775
4
fn one_tuple_inside_unwrapped_newtype_variant_inside_flatten_struct() {
776
16
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
777
    enum A {
778
        Newtype([i32; 1]),
779
    }
780

            
781
20
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
782
    struct B {
783
        a: A,
784
    }
785

            
786
24
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
787
    struct FlattenedStruct {
788
        ho: i32,
789
        #[serde(flatten)]
790
        a: B,
791
    }
792

            
793
4
    assert_eq!(
794
4
        check_roundtrip(
795
4
            &FlattenedStruct {
796
4
                ho: 24,
797
4
                a: B {
798
4
                    a: A::Newtype([42])
799
4
                }
800
4
            },
801
4
            PrettyConfig::default()
802
4
        ),
803
4
        Ok(())
804
4
    );
805
4
    assert_eq!(
806
4
        check_roundtrip(
807
4
            &FlattenedStruct {
808
4
                ho: 24,
809
4
                a: B {
810
4
                    a: A::Newtype([42])
811
4
                }
812
4
            },
813
4
            PrettyConfig::default().extensions(Extensions::UNWRAP_VARIANT_NEWTYPES)
814
4
        ),
815
4
        Err(Err(SpannedError {
816
4
            code: Error::InvalidValueForType {
817
4
                expected: String::from("an array of length 1"),
818
4
                found: String::from("the unsigned integer `42`")
819
4
            },
820
4
            position: Position { line: 5, col: 1 }
821
4
        }))
822
4
    );
823
4
}
824

            
825
#[test]
826
4
fn one_tuple_inside_unwrapped_newtype_variant_inside_flatten_struct_variant() {
827
16
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
828
    enum A {
829
        Newtype((i32,)),
830
    }
831

            
832
20
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
833
    struct B {
834
        a: A,
835
    }
836

            
837
40
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
838
    enum FlattenedStructVariant {
839
        C {
840
            ho: i32,
841
            #[serde(flatten)]
842
            a: B,
843
        },
844
    }
845

            
846
4
    assert_eq!(
847
4
        check_roundtrip(
848
4
            &FlattenedStructVariant::C {
849
4
                ho: 24,
850
4
                a: B {
851
4
                    a: A::Newtype((42,))
852
4
                }
853
4
            },
854
4
            PrettyConfig::default()
855
4
        ),
856
4
        Ok(()),
857
4
    );
858
4
    assert_eq!(
859
4
        check_roundtrip(
860
4
            &FlattenedStructVariant::C {
861
4
                ho: 24,
862
4
                a: B {
863
4
                    a: A::Newtype((42,))
864
4
                }
865
4
            },
866
4
            PrettyConfig::default().extensions(Extensions::UNWRAP_VARIANT_NEWTYPES)
867
4
        ),
868
4
        Err(Err(SpannedError {
869
4
            code: Error::InvalidValueForType {
870
4
                expected: String::from("a tuple of size 1"),
871
4
                found: String::from("the unsigned integer `42`")
872
4
            },
873
4
            position: Position { line: 5, col: 1 }
874
4
        }))
875
4
    );
876
4
}
877

            
878
#[test]
879
4
fn one_tuple_variant_inside_internally_tagged() {
880
    // A tuple variant with just one element that is not a newtype variant
881
8
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
882
    enum OneEnum {
883
        OneTuple(i32, #[serde(skip)] ()),
884
    }
885

            
886
12
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
887
    struct A {
888
        hi: OneEnum,
889
    }
890

            
891
16
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
892
    #[serde(tag = "tag")]
893
    enum InternallyTagged {
894
        B { ho: i32, a: A },
895
    }
896

            
897
4
    assert_eq!(
898
4
        check_roundtrip(
899
4
            &InternallyTagged::B {
900
4
                ho: 24,
901
4
                a: A {
902
4
                    hi: OneEnum::OneTuple(42, ())
903
4
                }
904
4
            },
905
4
            PrettyConfig::default()
906
4
        ),
907
4
        Err(Err(SpannedError {
908
4
            code: Error::InvalidValueForType {
909
4
                expected: String::from("tuple variant"),
910
4
                found: String::from("the unsigned integer `42`")
911
4
            },
912
4
            position: Position { line: 7, col: 2 }
913
4
        }))
914
4
    );
915
4
}
916

            
917
#[test]
918
4
fn one_tuple_variant_inside_adjacently_tagged() {
919
    // A tuple variant with just one element that is not a newtype variant
920
32
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
921
    enum OneEnum {
922
        OneTuple(i32, #[serde(skip)] ()),
923
    }
924

            
925
28
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
926
    struct A {
927
        hi: OneEnum,
928
    }
929

            
930
68
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
931
    #[serde(tag = "tag", content = "content")]
932
    enum AdjacentlyTagged {
933
        B { ho: i32, a: A },
934
    }
935

            
936
4
    assert_eq!(
937
4
        check_roundtrip(
938
4
            &AdjacentlyTagged::B {
939
4
                ho: 24,
940
4
                a: A {
941
4
                    hi: OneEnum::OneTuple(42, ())
942
4
                }
943
4
            },
944
4
            PrettyConfig::default()
945
4
        ),
946
4
        Ok(())
947
4
    );
948
4
    assert_eq!(
949
4
        ron::from_str::<AdjacentlyTagged>("(tag: B, content: (ho: 24, a: (hi: OneTuple(42))))"),
950
4
        Ok(AdjacentlyTagged::B {
951
4
            ho: 24,
952
4
            a: A {
953
4
                hi: OneEnum::OneTuple(42, ())
954
4
            }
955
4
        }),
956
4
    );
957
4
    assert_eq!(
958
4
        ron::from_str::<AdjacentlyTagged>("(content: (ho: 24, a: (hi: OneTuple(42))), tag: B)"),
959
4
        Err(SpannedError {
960
4
            code: Error::InvalidValueForType {
961
4
                expected: String::from("tuple variant"),
962
4
                found: String::from("the unsigned integer `42`")
963
4
            },
964
4
            position: Position { line: 1, col: 50 }
965
4
        })
966
4
    );
967
4
}
968

            
969
#[test]
970
4
fn one_tuple_variant_inside_untagged() {
971
    // A tuple variant with just one element that is not a newtype variant
972
8
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
973
    enum OneEnum {
974
        OneTuple(i32, #[serde(skip)] ()),
975
    }
976

            
977
12
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
978
    struct A {
979
        hi: OneEnum,
980
    }
981

            
982
12
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
983
    #[serde(untagged)]
984
    enum Untagged {
985
        B { ho: i32, a: A },
986
    }
987

            
988
4
    assert_eq!(
989
4
        check_roundtrip(
990
4
            &Untagged::B {
991
4
                ho: 24,
992
4
                a: A {
993
4
                    hi: OneEnum::OneTuple(42, ())
994
4
                }
995
4
            },
996
4
            PrettyConfig::default()
997
4
        ),
998
4
        Err(Err(SpannedError {
999
4
            code: Error::Message(String::from(
4
                "data did not match any variant of untagged enum Untagged"
4
            )),
4
            position: Position { line: 6, col: 2 }
4
        }))
4
    );
4
}
#[test]
4
fn one_tuple_variant_inside_flatten_struct() {
    // A tuple variant with just one element that is not a newtype variant
8
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    enum OneEnum {
        OneTuple(i32, #[serde(skip)] ()),
    }
12
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct A {
        hi: OneEnum,
    }
12
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct B {
        a: A,
    }
12
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct FlattenedStruct {
        ho: i32,
        #[serde(flatten)]
        a: B,
    }
4
    assert_eq!(
4
        check_roundtrip(
4
            &FlattenedStruct {
4
                ho: 24,
4
                a: B {
4
                    a: A {
4
                        hi: OneEnum::OneTuple(42, ())
4
                    }
4
                }
4
            },
4
            PrettyConfig::default()
4
        ),
4
        Err(Err(SpannedError {
4
            code: Error::InvalidValueForType {
4
                expected: String::from("tuple variant"),
4
                found: String::from("the unsigned integer `42`")
4
            },
4
            position: Position { line: 6, col: 1 }
4
        }))
4
    );
4
}
#[test]
4
fn one_tuple_variant_inside_flatten_struct_variant() {
    // A tuple variant with just one element that is not a newtype variant
8
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    enum OneEnum {
        OneTuple(i32, #[serde(skip)] ()),
    }
12
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct A {
        hi: OneEnum,
    }
12
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct B {
        a: A,
    }
20
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    enum FlattenedStructVariant {
        C {
            ho: i32,
            #[serde(flatten)]
            a: B,
        },
    }
4
    assert_eq!(
4
        check_roundtrip(
4
            &FlattenedStructVariant::C {
4
                ho: 24,
4
                a: B {
4
                    a: A {
4
                        hi: OneEnum::OneTuple(42, ())
4
                    }
4
                }
4
            },
4
            PrettyConfig::default()
4
        ),
4
        Err(Err(SpannedError {
4
            code: Error::InvalidValueForType {
4
                expected: String::from("tuple variant"),
4
                found: String::from("the unsigned integer `42`")
4
            },
4
            position: Position { line: 6, col: 1 }
4
        }))
4
    );
4
}
#[test]
4
fn raw_value_inside_internally_tagged() {
12
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct A {
        hi: Box<ron::value::RawValue>,
    }
16
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    #[serde(tag = "tag")]
    enum InternallyTagged {
        B { ho: i32, a: A },
    }
4
    assert_eq!(
4
        check_roundtrip(
4
            &InternallyTagged::B {
4
                ho: 24,
4
                a: A {
4
                    hi: ron::value::RawValue::from_boxed_ron(String::from("42").into_boxed_str())
4
                        .unwrap(),
4
                }
4
            },
4
            PrettyConfig::default()
4
        ),
4
        Err(Err(SpannedError {
4
            code: Error::InvalidValueForType {
4
                expected: String::from("any valid RON-value-string"),
4
                found: String::from("the unsigned integer `42`")
4
            },
4
            position: Position { line: 7, col: 2 }
4
        }))
4
    );
4
}
#[test]
4
fn raw_value_inside_adjacently_tagged() {
28
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct A {
        hi: Box<ron::value::RawValue>,
    }
68
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    #[serde(tag = "tag", content = "content")]
    enum AdjacentlyTagged {
        B { ho: i32, a: A },
    }
4
    assert_eq!(
4
        check_roundtrip(
4
            &AdjacentlyTagged::B {
4
                ho: 24,
4
                a: A {
4
                    hi: ron::value::RawValue::from_boxed_ron(String::from("42").into_boxed_str())
4
                        .unwrap(),
4
                }
4
            },
4
            PrettyConfig::default()
4
        ),
4
        // adds an extra space
4
        Err(Ok(Error::Message(String::from("ROUNDTRIP error: B { ho: 24, a: A { hi: RawValue(42) } } != B { ho: 24, a: A { hi: RawValue( 42) } }"))))
4
    );
4
    assert_eq!(
4
        ron::from_str::<AdjacentlyTagged>("(tag: B, content: (ho: 24, a: (hi:42)))"),
4
        Ok(AdjacentlyTagged::B {
4
            ho: 24,
4
            a: A {
4
                hi: ron::value::RawValue::from_boxed_ron(String::from("42").into_boxed_str())
4
                    .unwrap(),
4
            }
4
        }),
4
    );
4
    assert_eq!(
4
        ron::from_str::<AdjacentlyTagged>("(content: (ho: 24, a: (hi:42)), tag: B)"),
4
        Err(SpannedError {
4
            code: Error::InvalidValueForType {
4
                expected: String::from("any valid RON-value-string"),
4
                found: String::from("the unsigned integer `42`")
4
            },
4
            position: Position { line: 1, col: 39 }
4
        })
4
    );
4
}
#[test]
4
fn raw_value_inside_untagged() {
12
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct A {
        hi: Box<ron::value::RawValue>,
    }
12
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    #[serde(untagged)]
    enum Untagged {
        B { ho: i32, a: A },
    }
4
    assert_eq!(
4
        check_roundtrip(
4
            &Untagged::B {
4
                ho: 24,
4
                a: A {
4
                    hi: ron::value::RawValue::from_boxed_ron(String::from("42").into_boxed_str())
4
                        .unwrap(),
4
                }
4
            },
4
            PrettyConfig::default()
4
        ),
4
        Err(Err(SpannedError {
4
            code: Error::Message(String::from(
4
                "data did not match any variant of untagged enum Untagged"
4
            )),
4
            position: Position { line: 6, col: 2 }
4
        }))
4
    );
4
}
#[test]
4
fn raw_value_inside_flatten_struct() {
12
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct A {
        hi: Box<ron::value::RawValue>,
    }
12
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct B {
        a: A,
    }
12
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct FlattenedStruct {
        ho: i32,
        #[serde(flatten)]
        a: B,
    }
4
    assert_eq!(
4
        check_roundtrip(
4
            &FlattenedStruct {
4
                ho: 24,
4
                a: B {
4
                    a: A {
4
                        hi: ron::value::RawValue::from_boxed_ron(
4
                            String::from("42").into_boxed_str()
4
                        )
4
                        .unwrap(),
4
                    }
4
                }
4
            },
4
            PrettyConfig::default()
4
        ),
4
        Err(Err(SpannedError {
4
            code: Error::InvalidValueForType {
4
                expected: String::from("any valid RON-value-string"),
4
                found: String::from("the unsigned integer `42`")
4
            },
4
            position: Position { line: 6, col: 1 }
4
        }))
4
    );
4
}
#[test]
4
fn raw_value_inside_flatten_struct_variant() {
12
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct A {
        hi: Box<ron::value::RawValue>,
    }
12
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct B {
        a: A,
    }
20
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    enum FlattenedStructVariant {
        C {
            ho: i32,
            #[serde(flatten)]
            a: B,
        },
    }
4
    assert_eq!(
4
        check_roundtrip(
4
            &FlattenedStructVariant::C {
4
                ho: 24,
4
                a: B {
4
                    a: A {
4
                        hi: ron::value::RawValue::from_boxed_ron(
4
                            String::from("42").into_boxed_str()
4
                        )
4
                        .unwrap(),
4
                    }
4
                }
4
            },
4
            PrettyConfig::default()
4
        ),
4
        Err(Err(SpannedError {
4
            code: Error::InvalidValueForType {
4
                expected: String::from("any valid RON-value-string"),
4
                found: String::from("the unsigned integer `42`")
4
            },
4
            position: Position { line: 6, col: 1 }
4
        }))
4
    );
4
}
#[test]
4
fn unit_like_zero_length_inside_internally_tagged() {
12
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct A {
        hi: [i32; 0],
    }
16
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    #[serde(tag = "tag")]
    enum InternallyTagged {
        B { ho: i32, a: A },
    }
4
    assert_eq!(
4
        check_roundtrip(
4
            &InternallyTagged::B {
4
                ho: 24,
4
                a: A { hi: [] }
4
            },
4
            PrettyConfig::default()
4
        ),
4
        Err(Err(SpannedError {
4
            code: Error::InvalidValueForType {
4
                expected: String::from("an empty array"),
4
                found: String::from("a unit value")
4
            },
4
            position: Position { line: 7, col: 2 }
4
        }))
4
    );
4
}
#[test]
4
fn unit_like_zero_length_inside_adjacently_tagged() {
12
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct TupleStruct();
28
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct A {
        hi: TupleStruct,
    }
68
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    #[serde(tag = "tag", content = "content")]
    enum AdjacentlyTagged {
        B { ho: i32, a: A },
    }
4
    assert_eq!(
4
        check_roundtrip(
4
            &AdjacentlyTagged::B {
4
                ho: 24,
4
                a: A { hi: TupleStruct() }
4
            },
4
            PrettyConfig::default()
4
        ),
4
        Ok(()),
4
    );
4
    assert_eq!(
4
        ron::from_str::<AdjacentlyTagged>("(tag: B, content: (ho: 24, a: (hi: ())))"),
4
        Ok(AdjacentlyTagged::B {
4
            ho: 24,
4
            a: A { hi: TupleStruct() }
4
        }),
4
    );
4
    assert_eq!(
4
        ron::from_str::<AdjacentlyTagged>("(content: (ho: 24, a: (hi: ())), tag: B)"),
4
        Err(SpannedError {
4
            code: Error::InvalidValueForType {
4
                expected: String::from("tuple struct TupleStruct"),
4
                found: String::from("a unit value")
4
            },
4
            position: Position { line: 1, col: 40 }
4
        })
4
    );
4
}
#[test]
4
fn unit_like_zero_length_inside_untagged() {
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct Struct {}
12
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct A {
        hi: Struct,
    }
12
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    #[serde(untagged)]
    enum Untagged {
        B { ho: i32, a: A },
    }
4
    assert_eq!(
4
        check_roundtrip(
4
            &Untagged::B {
4
                ho: 24,
4
                a: A { hi: Struct {} }
4
            },
4
            PrettyConfig::default()
4
        ),
4
        Err(Err(SpannedError {
4
            code: Error::Message(String::from(
4
                "data did not match any variant of untagged enum Untagged"
4
            )),
4
            position: Position { line: 6, col: 2 }
4
        }))
4
    );
4
}
#[test]
4
fn unit_like_zero_length_inside_flatten_struct() {
8
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    enum Enum {
        Tuple(),
    }
12
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct A {
        hi: Enum,
    }
12
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct B {
        a: A,
    }
12
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct FlattenedStruct {
        ho: i32,
        #[serde(flatten)]
        a: B,
    }
4
    assert_eq!(
4
        check_roundtrip(
4
            &FlattenedStruct {
4
                ho: 24,
4
                a: B {
4
                    a: A { hi: Enum::Tuple() }
4
                }
4
            },
4
            PrettyConfig::default()
4
        ),
4
        Err(Err(SpannedError {
4
            code: Error::InvalidValueForType {
4
                expected: String::from("tuple variant"),
4
                found: String::from("a unit value")
4
            },
4
            position: Position { line: 6, col: 1 }
4
        }))
4
    );
4
}
#[test]
4
fn unit_like_zero_length_inside_flatten_struct_variant() {
8
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    enum Enum {
        Struct {},
    }
12
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct A {
        hi: Enum,
    }
12
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct B {
        a: A,
    }
20
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    enum FlattenedStructVariant {
        C {
            ho: i32,
            #[serde(flatten)]
            a: B,
        },
    }
4
    assert_eq!(
4
        check_roundtrip(
4
            &FlattenedStructVariant::C {
4
                ho: 24,
4
                a: B {
4
                    a: A {
4
                        hi: Enum::Struct {}
4
                    }
4
                }
4
            },
4
            PrettyConfig::default()
4
        ),
4
        Err(Err(SpannedError {
4
            code: Error::InvalidValueForType {
4
                expected: String::from("struct variant"),
4
                found: String::from("a unit value")
4
            },
4
            position: Position { line: 6, col: 1 }
4
        }))
4
    );
4
}
#[test]
4
fn i128_inside_internally_tagged() {
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct A {
        hi: i128,
    }
2
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    #[serde(tag = "tag")]
    enum InternallyTagged {
        B { ho: i32, a: A },
    }
    #[cfg(not(feature = "integer128"))]
2
    assert_eq!(
2
        check_roundtrip(
2
            &InternallyTagged::B {
2
                ho: 24,
2
                a: A { hi: i128::MAX }
2
            },
2
            PrettyConfig::default()
2
        ),
2
        Err(Ok(Error::Message(String::from("i128 is not supported"))))
2
    );
    #[cfg(feature = "integer128")]
2
    assert_eq!(
2
        check_roundtrip(
2
            &InternallyTagged::B {
2
                ho: 24,
2
                a: A { hi: i128::MAX }
2
            },
2
            PrettyConfig::default()
2
        ),
2
        Err(Err(SpannedError {
2
            code: Error::InvalidValueForType {
2
                expected: String::from("any value"),
2
                found: format!("integer `{}` as u128", i128::MAX)
2
            },
2
            position: Position { line: 5, col: 52 }
2
        }))
2
    );
4
}
#[test]
4
fn u128_inside_adjacently_tagged() {
8
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct A {
        hi: u128,
    }
30
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    #[serde(tag = "tag", content = "content")]
    enum AdjacentlyTagged {
        B { ho: i32, a: A },
    }
    #[cfg(not(feature = "integer128"))]
2
    assert_eq!(
2
        check_roundtrip(
2
            &AdjacentlyTagged::B {
2
                ho: 24,
2
                a: A { hi: u128::MAX }
2
            },
2
            PrettyConfig::default()
2
        ),
2
        Err(Ok(Error::Message(String::from("u128 is not supported"))))
2
    );
    #[cfg(feature = "integer128")]
2
    assert_eq!(
2
        check_roundtrip(
2
            &AdjacentlyTagged::B {
2
                ho: 24,
2
                a: A { hi: u128::MAX }
2
            },
2
            PrettyConfig::default()
2
        ),
2
        Ok(()),
2
    );
    #[cfg(feature = "integer128")]
2
    assert_eq!(
2
        ron::from_str::<AdjacentlyTagged>(&format!(
2
            "(tag: B, content: (ho: 24, a: (hi: {})))",
2
            u128::MAX
2
        ),),
2
        Ok(AdjacentlyTagged::B {
2
            ho: 24,
2
            a: A { hi: u128::MAX }
2
        }),
2
    );
    #[cfg(feature = "integer128")]
2
    assert_eq!(
2
        ron::from_str::<AdjacentlyTagged>(&format!(
2
            "(content: (ho: 24, a: (hi: {})), tag: B)",
2
            u128::MAX
2
        ),),
2
        Err(SpannedError {
2
            code: Error::InvalidValueForType {
2
                expected: String::from("any value"),
2
                found: format!("integer `{}` as u128", u128::MAX)
2
            },
2
            position: Position { line: 1, col: 67 }
2
        }),
2
    );
4
}
#[test]
4
fn i128_inside_untagged() {
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct A {
        hi: i128,
    }
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    #[serde(untagged)]
    enum Untagged {
        B { ho: i32, a: A },
    }
    #[cfg(not(feature = "integer128"))]
2
    assert_eq!(
2
        check_roundtrip(
2
            &Untagged::B {
2
                ho: 24,
2
                a: A { hi: i128::MIN }
2
            },
2
            PrettyConfig::default()
2
        ),
2
        Err(Ok(Error::Message(String::from("i128 is not supported"))))
2
    );
    #[cfg(feature = "integer128")]
2
    assert_eq!(
2
        check_roundtrip(
2
            &Untagged::B {
2
                ho: 24,
2
                a: A { hi: i128::MIN }
2
            },
2
            PrettyConfig::default()
2
        ),
2
        Err(Err(SpannedError {
2
            code: Error::InvalidValueForType {
2
                expected: String::from("any value"),
2
                found: format!("integer `{}` as i128", i128::MIN)
2
            },
2
            position: Position { line: 4, col: 53 }
2
        }))
2
    );
4
}
#[test]
4
fn u128_inside_flatten_struct() {
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct A {
        hi: u128,
    }
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct B {
        a: A,
    }
6
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct FlattenedStruct {
        ho: i32,
        #[serde(flatten)]
        a: B,
    }
    #[cfg(not(feature = "integer128"))]
2
    assert_eq!(
2
        check_roundtrip(
2
            &FlattenedStruct {
2
                ho: 24,
2
                a: B {
2
                    a: A { hi: u128::MAX }
2
                }
2
            },
2
            PrettyConfig::default()
2
        ),
2
        Err(Ok(Error::Message(String::from("u128 is not supported"))))
2
    );
    #[cfg(feature = "integer128")]
2
    assert_eq!(
2
        check_roundtrip(
2
            &FlattenedStruct {
2
                ho: 24,
2
                a: B {
2
                    a: A { hi: u128::MAX }
2
                }
2
            },
2
            PrettyConfig::default()
2
        ),
2
        Err(Err(SpannedError {
2
            code: Error::InvalidValueForType {
2
                expected: String::from("any value"),
2
                found: format!("integer `{}` as u128", u128::MAX)
2
            },
2
            position: Position { line: 4, col: 52 }
2
        }))
2
    );
4
}
#[test]
4
fn i128_inside_flatten_struct_variant() {
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct A {
        hi: i128,
    }
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct B {
        a: A,
    }
14
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    enum FlattenedStructVariant {
        C {
            ho: i32,
            #[serde(flatten)]
            a: B,
        },
    }
    #[cfg(not(feature = "integer128"))]
2
    assert_eq!(
2
        check_roundtrip(
2
            &FlattenedStructVariant::C {
2
                ho: 24,
2
                a: B {
2
                    a: A { hi: i128::MIN }
2
                }
2
            },
2
            PrettyConfig::default()
2
        ),
2
        Err(Ok(Error::Message(String::from("i128 is not supported"))))
2
    );
    #[cfg(feature = "integer128")]
2
    assert_eq!(
2
        check_roundtrip(
2
            &FlattenedStructVariant::C {
2
                ho: 24,
2
                a: B {
2
                    a: A { hi: i128::MIN }
2
                }
2
            },
2
            PrettyConfig::default()
2
        ),
2
        Err(Err(SpannedError {
2
            code: Error::InvalidValueForType {
2
                expected: String::from("any value"),
2
                found: format!("integer `{}` as i128", i128::MIN)
2
            },
2
            position: Position { line: 4, col: 53 }
2
        }))
2
    );
4
}
#[test]
4
fn duplicate_key_inside_flatten_struct() {
12
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct FlattenedStruct {
        ho: i32,
        #[serde(flatten)]
        other: HashMap<String, i32>,
    }
4
    assert_eq!(
4
        check_roundtrip(
4
            &FlattenedStruct {
4
                ho: 24,
4
                other: [(String::from("ho"), 42)].into_iter().collect(),
4
            },
4
            PrettyConfig::default()
4
        ),
4
        Err(Err(SpannedError {
4
            code: Error::DuplicateStructField {
4
                field: "ho",
4
                outer: None
4
            },
4
            position: Position { line: 3, col: 9 }
4
        }))
4
    );
4
}
#[test]
4
fn duplicate_key_inside_flatten_struct_variant() {
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct C {
        ho: i32,
        hi: bool,
    }
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct B {
        #[serde(flatten)]
        inner: C,
    }
20
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    enum FlattenedStructVariant {
        A {
            ho: i32,
            #[serde(flatten)]
            inner: B,
        },
    }
4
    assert_eq!(
4
        check_roundtrip(
4
            &FlattenedStructVariant::A {
4
                ho: 24,
4
                inner: B {
4
                    inner: C { ho: 42, hi: false }
4
                }
4
            },
4
            PrettyConfig::default()
4
        ),
4
        Err(Err(SpannedError {
4
            code: Error::DuplicateStructField {
4
                field: "ho",
4
                outer: Some(String::from("A"))
4
            },
4
            position: Position { line: 3, col: 9 }
4
        }))
4
    );
4
}
#[test]
4
fn non_string_key_inside_flatten_struct() {
8
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct FlattenedStruct {
        ho: i32,
        #[serde(flatten)]
        other: HashMap<i32, bool>,
    }
4
    assert_eq!(
4
        check_roundtrip(
4
            &FlattenedStruct {
4
                ho: 24,
4
                other: [(1, true), (0, false)].into_iter().collect(),
4
            },
4
            PrettyConfig::default()
4
        ),
4
        Err(Err(SpannedError {
4
            code: Error::ExpectedString,
4
            position: Position { line: 3, col: 5 }
4
        }))
4
    );
4
}
#[test]
4
fn non_string_key_inside_flatten_struct_variant() {
16
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    enum FlattenedStructVariant {
        A {
            ho: i32,
            #[serde(flatten)]
            other: HashMap<char, u8>,
        },
    }
4
    assert_eq!(
4
        check_roundtrip(
4
            &FlattenedStructVariant::A {
4
                ho: 24,
4
                other: [('h', 0), ('i', 1)].into_iter().collect(),
4
            },
4
            PrettyConfig::default()
4
        ),
4
        Err(Err(SpannedError {
4
            code: Error::ExpectedString,
4
            position: Position { line: 3, col: 5 }
4
        }))
4
    );
4
}
#[test]
4
fn more_than_one_flatten_map_inside_flatten_struct() {
4
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct Deep {
        #[serde(flatten)]
        other: HashMap<String, bool>,
    }
4
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct Inner {
        #[serde(flatten)]
        deep: Deep,
    }
12
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct FlattenedStruct {
        ho: i32,
        #[serde(flatten)]
        hi: Inner,
        #[serde(flatten)]
        other: HashMap<String, bool>,
    }
4
    assert_eq!(
4
        check_roundtrip(
4
            &FlattenedStruct {
4
                ho: 24,
4
                hi: Inner {
4
                    deep: Deep {
4
                        other: HashMap::new(),
4
                    },
4
                },
4
                other: [(String::from("42"), true)].into_iter().collect(),
4
            },
4
            PrettyConfig::default()
4
        ),
4
        // both maps collect all the unknown keys
4
        Err(Ok(Error::Message(String::from("ROUNDTRIP error: FlattenedStruct { ho: 24, hi: Inner { deep: Deep { other: {} } }, other: {\"42\": true} } != FlattenedStruct { ho: 24, hi: Inner { deep: Deep { other: {\"42\": true} } }, other: {\"42\": true} }"))))
4
    );
4
}
#[test]
4
fn more_than_one_flatten_map_inside_flatten_struct_variant() {
4
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct Deep {
        #[serde(flatten)]
        other: HashMap<String, bool>,
    }
4
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct Inner {
        #[serde(flatten)]
        deep: Deep,
    }
20
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    enum FlattenedStructVariant {
        A {
            ho: i32,
            #[serde(flatten)]
            hi: Inner,
            #[serde(flatten)]
            other: HashMap<String, bool>,
        },
    }
4
    assert_eq!(
4
        check_roundtrip(
4
            &FlattenedStructVariant::A {
4
                ho: 24,
4
                hi: Inner {
4
                    deep: Deep {
4
                        other: [(String::from("24"), false)].into_iter().collect(),
4
                    },
4
                },
4
                other: HashMap::new(),
4
            },
4
            PrettyConfig::default()
4
        ),
4
        // both maps collect all the unknown keys
4
        Err(Ok(Error::Message(String::from("ROUNDTRIP error: A { ho: 24, hi: Inner { deep: Deep { other: {\"24\": false} } }, other: {} } != A { ho: 24, hi: Inner { deep: Deep { other: {\"24\": false} } }, other: {\"24\": false} }"))))
4
    );
4
}
#[test]
4
fn flatten_struct_beside_map_inside_flatten_struct() {
    // The non-flattened struct must contain some flattened fields
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct Flattened {
        hi: i32,
        #[serde(flatten)]
        flat: (),
    }
    // The non-flattened struct must be behind a level of flatten
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct Inner {
        flat: Flattened,
    }
12
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct FlattenedStruct {
        ho: i32,
        #[serde(flatten)]
        other: HashMap<String, i32>,
        #[serde(flatten)]
        inner: Inner,
    }
4
    assert_eq!(
4
        check_roundtrip(
4
            &FlattenedStruct {
4
                ho: 24,
4
                other: HashMap::new(),
4
                inner: Inner {
4
                    flat: Flattened { hi: 42, flat: () },
4
                },
4
            },
4
            PrettyConfig::default()
4
        ),
4
        Err(Err(SpannedError {
4
            code: Error::InvalidValueForType {
4
                expected: String::from("i32"),
4
                found: String::from("a map")
4
            },
4
            position: Position { line: 6, col: 1 }
4
        }))
4
    );
4
}
#[test]
4
fn flatten_struct_beside_map_inside_flatten_struct_variant() {
    // The non-flattened struct must contain some flattened fields
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct Flattened {
        hi: i32,
        #[serde(flatten)]
        flat: (),
    }
    // The non-flattened struct must be behind a level of flatten
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct Inner {
        flat: Flattened,
    }
20
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    enum FlattenedStructVariant {
        A {
            ho: i32,
            #[serde(flatten)]
            other: HashMap<String, i32>,
            #[serde(flatten)]
            inner: Inner,
        },
    }
4
    assert_eq!(
4
        check_roundtrip(
4
            &FlattenedStructVariant::A {
4
                ho: 24,
4
                other: HashMap::new(),
4
                inner: Inner {
4
                    flat: Flattened { hi: 42, flat: () },
4
                },
4
            },
4
            PrettyConfig::default()
4
        ),
4
        Err(Err(SpannedError {
4
            code: Error::InvalidValueForType {
4
                expected: String::from("i32"),
4
                found: String::from("a map")
4
            },
4
            position: Position { line: 6, col: 1 }
4
        }))
4
    );
4
}
#[test]
4
fn untagged_flatten_struct_variant_beside_map_inside_flatten_struct() {
8
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    #[serde(untagged)]
    enum Flattened {
        Struct {
            hi: i32,
            #[serde(flatten)]
            flat: (),
        },
    }
12
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct FlattenedStruct {
        ho: i32,
        #[serde(flatten)]
        other: HashMap<String, i32>,
        #[serde(flatten)]
        flat: Flattened,
    }
4
    assert_eq!(
4
        check_roundtrip(
4
            &FlattenedStruct {
4
                ho: 24,
4
                other: HashMap::new(),
4
                flat: Flattened::Struct { hi: 42, flat: () },
4
            },
4
            PrettyConfig::default()
4
        ),
4
        Err(Ok(Error::Message(String::from("ROUNDTRIP error: FlattenedStruct { ho: 24, other: {}, flat: Struct { hi: 42, flat: () } } != FlattenedStruct { ho: 24, other: {\"hi\": 42}, flat: Struct { hi: 42, flat: () } }"))))
4
    );
4
}
#[test]
4
fn untagged_flatten_struct_variant_beside_map_inside_flatten_struct_variant() {
8
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    #[serde(untagged)]
    enum Flattened {
        Struct {
            hi: i32,
            #[serde(flatten)]
            flat: (),
        },
    }
20
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    enum FlattenedStructVariant {
        A {
            ho: i32,
            #[serde(flatten)]
            other: HashMap<String, i32>,
            #[serde(flatten)]
            flat: Flattened,
        },
    }
4
    assert_eq!(
4
        check_roundtrip(
4
            &FlattenedStructVariant::A {
4
                ho: 24,
4
                other: HashMap::new(),
4
                flat: Flattened::Struct { hi: 42, flat: () },
4
            },
4
            PrettyConfig::default()
4
        ),
4
        Err(Ok(Error::Message(String::from("ROUNDTRIP error: A { ho: 24, other: {}, flat: Struct { hi: 42, flat: () } } != A { ho: 24, other: {\"hi\": 42}, flat: Struct { hi: 42, flat: () } }"))))
4
    );
4
}
#[test]
4
fn externally_tagged_newtype_variant_beside_map_inside_flatten_struct_variant() {
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    enum Flattened {
        Newtype(()),
    }
20
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    enum FlattenedStructVariant {
        A {
            ho: i32,
            #[serde(flatten)]
            other: HashMap<String, i32>,
            #[serde(flatten)]
            flat: Flattened,
        },
    }
4
    assert_eq!(
4
        check_roundtrip(
4
            &FlattenedStructVariant::A {
4
                ho: 24,
4
                other: HashMap::new(),
4
                flat: Flattened::Newtype(()),
4
            },
4
            PrettyConfig::default()
4
        ),
4
        Err(Err(SpannedError {
4
            code: Error::InvalidValueForType {
4
                expected: String::from("i32"),
4
                found: String::from("a unit value")
4
            },
4
            position: Position { line: 4, col: 1 }
4
        }))
4
    );
4
}
#[test]
4
fn externally_tagged_struct_variant_beside_map_inside_flatten_struct() {
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    enum Flattened {
        Struct { hi: i32 },
    }
12
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct FlattenedStruct {
        ho: i32,
        #[serde(flatten)]
        other: HashMap<String, i32>,
        #[serde(flatten)]
        flat: Flattened,
    }
4
    assert_eq!(
4
        check_roundtrip(
4
            &FlattenedStruct {
4
                ho: 24,
4
                other: HashMap::new(),
4
                flat: Flattened::Struct { hi: 42 },
4
            },
4
            PrettyConfig::default()
4
        ),
4
        Err(Err(SpannedError {
4
            code: Error::InvalidValueForType {
4
                expected: String::from("i32"),
4
                found: String::from("a map")
4
            },
4
            position: Position { line: 6, col: 1 }
4
        }))
4
    );
4
}
#[test]
4
fn externally_tagged_tuple_variant_beside_map_inside_flatten_struct_variant() {
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    enum Flattened {
        Tuple(i32, bool),
    }
20
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    enum FlattenedStructVariant {
        A {
            ho: i32,
            #[serde(flatten)]
            other: HashMap<String, i32>,
            #[serde(flatten)]
            flat: Flattened,
        },
    }
4
    assert_eq!(
4
        check_roundtrip(
4
            &FlattenedStructVariant::A {
4
                ho: 24,
4
                other: HashMap::new(),
4
                flat: Flattened::Tuple(42, true),
4
            },
4
            PrettyConfig::default()
4
        ),
4
        Err(Err(SpannedError {
4
            code: Error::InvalidValueForType {
4
                expected: String::from("i32"),
4
                found: String::from("a sequence")
4
            },
4
            position: Position { line: 7, col: 1 }
4
        }))
4
    );
4
}
#[test]
4
fn internally_tagged_unit_variant_beside_map_inside_flatten_struct() {
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    #[serde(tag = "tag")]
    enum Flattened {
        Unit,
    }
12
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct FlattenedStruct {
        ho: i32,
        #[serde(flatten)]
        other: HashMap<String, i32>,
        #[serde(flatten)]
        flat: Flattened,
    }
4
    assert_eq!(
4
        check_roundtrip(
4
            &FlattenedStruct {
4
                ho: 24,
4
                other: HashMap::new(),
4
                flat: Flattened::Unit,
4
            },
4
            PrettyConfig::default()
4
        ),
4
        Err(Err(SpannedError {
4
            code: Error::InvalidValueForType {
4
                expected: String::from("i32"),
4
                found: String::from("the string \"Unit\"")
4
            },
4
            position: Position { line: 4, col: 1 }
4
        }))
4
    );
4
}
#[test]
4
fn internally_tagged_newtype_variant_beside_map_inside_flatten_struct_variant() {
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    #[serde(tag = "tag")]
    enum Flattened {
        Newtype(()),
    }
20
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    enum FlattenedStructVariant {
        A {
            ho: i32,
            #[serde(flatten)]
            other: HashMap<String, i32>,
            #[serde(flatten)]
            flat: Flattened,
        },
    }
4
    assert_eq!(
4
        check_roundtrip(
4
            &FlattenedStructVariant::A {
4
                ho: 24,
4
                other: HashMap::new(),
4
                flat: Flattened::Newtype(()),
4
            },
4
            PrettyConfig::default()
4
        ),
4
        Err(Err(SpannedError {
4
            code: Error::InvalidValueForType {
4
                expected: String::from("i32"),
4
                found: String::from("the string \"Newtype\"")
4
            },
4
            position: Position { line: 4, col: 1 }
4
        }))
4
    );
4
}
#[test]
4
fn internally_tagged_struct_variant_beside_map_inside_flatten_struct() {
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    #[serde(tag = "tag")]
    enum Flattened {
        Struct { hi: i32 },
    }
16
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct FlattenedStruct {
        ho: i32,
        #[serde(flatten)]
        other: HashMap<String, i32>,
        #[serde(flatten)]
        flat: Flattened,
    }
4
    assert_eq!(
4
        check_roundtrip(
4
            &FlattenedStruct {
4
                ho: 24,
4
                other: HashMap::new(),
4
                flat: Flattened::Struct { hi: 42 },
4
            },
4
            PrettyConfig::default()
4
        ),
4
        Err(Err(SpannedError {
4
            code: Error::InvalidValueForType {
4
                expected: String::from("i32"),
4
                found: String::from("the string \"Struct\"")
4
            },
4
            position: Position { line: 5, col: 1 }
4
        }))
4
    );
4
}
#[test]
4
fn adjacently_tagged_unit_variant_beside_map_inside_flatten_struct() {
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    #[serde(tag = "tag", content = "content")]
    enum Flattened {
        Unit,
    }
12
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct FlattenedStruct {
        ho: i32,
        #[serde(flatten)]
        other: HashMap<String, i32>,
        #[serde(flatten)]
        flat: Flattened,
    }
4
    assert_eq!(
4
        check_roundtrip(
4
            &FlattenedStruct {
4
                ho: 24,
4
                other: HashMap::new(),
4
                flat: Flattened::Unit,
4
            },
4
            PrettyConfig::default()
4
        ),
4
        Err(Err(SpannedError {
4
            code: Error::InvalidValueForType {
4
                expected: String::from("i32"),
4
                found: String::from("the string \"Unit\"")
4
            },
4
            position: Position { line: 4, col: 1 }
4
        }))
4
    );
4
}
#[test]
4
fn adjacently_tagged_newtype_variant_beside_map_inside_flatten_struct_variant() {
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    #[serde(tag = "tag", content = "content")]
    enum Flattened {
        Newtype(()),
    }
24
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    enum FlattenedStructVariant {
        A {
            ho: i32,
            #[serde(flatten)]
            other: HashMap<String, i32>,
            #[serde(flatten)]
            flat: Flattened,
        },
    }
4
    assert_eq!(
4
        check_roundtrip(
4
            &FlattenedStructVariant::A {
4
                ho: 24,
4
                other: HashMap::new(),
4
                flat: Flattened::Newtype(()),
4
            },
4
            PrettyConfig::default()
4
        ),
4
        Err(Err(SpannedError {
4
            code: Error::InvalidValueForType {
4
                expected: String::from("i32"),
4
                found: String::from("the string \"Newtype\"")
4
            },
4
            position: Position { line: 5, col: 1 }
4
        }))
4
    );
4
}
#[test]
4
fn adjacently_tagged_struct_variant_beside_map_inside_flatten_struct() {
4
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    #[serde(tag = "tag", content = "content")]
    enum Flattened {
        Struct { hi: i32 },
    }
16
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct FlattenedStruct {
        ho: i32,
        #[serde(flatten)]
        other: HashMap<String, i32>,
        #[serde(flatten)]
        flat: Flattened,
    }
4
    assert_eq!(
4
        check_roundtrip(
4
            &FlattenedStruct {
4
                ho: 24,
4
                other: HashMap::new(),
4
                flat: Flattened::Struct { hi: 42 },
4
            },
4
            PrettyConfig::default()
4
        ),
4
        Err(Err(SpannedError {
4
            code: Error::InvalidValueForType {
4
                expected: String::from("i32"),
4
                found: String::from("the string \"Struct\"")
4
            },
4
            position: Position { line: 7, col: 1 }
4
        }))
4
    );
4
}
#[test]
4
fn adjacently_tagged_tuple_variant_beside_map_inside_flatten_struct_variant() {
4
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    #[serde(tag = "tag", content = "content")]
    enum Flattened {
        Tuple(i32, bool),
    }
24
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    enum FlattenedStructVariant {
        A {
            ho: i32,
            #[serde(flatten)]
            other: HashMap<String, i32>,
            #[serde(flatten)]
            flat: Flattened,
        },
    }
4
    assert_eq!(
4
        check_roundtrip(
4
            &FlattenedStructVariant::A {
4
                ho: 24,
4
                other: HashMap::new(),
4
                flat: Flattened::Tuple(42, true),
4
            },
4
            PrettyConfig::default()
4
        ),
4
        Err(Err(SpannedError {
4
            code: Error::InvalidValueForType {
4
                expected: String::from("i32"),
4
                found: String::from("the string \"Tuple\"")
4
            },
4
            position: Position { line: 5, col: 1 }
4
        }))
4
    );
4
}
#[test]
4
fn tagged_struct_beside_map_inside_flatten_struct() {
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    #[serde(tag = "tag")]
    struct Flattened {
        hi: i32,
    }
16
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct FlattenedStruct {
        ho: i32,
        #[serde(flatten)]
        other: HashMap<String, i32>,
        #[serde(flatten)]
        flat: Flattened,
    }
4
    assert_eq!(
4
        check_roundtrip(
4
            &FlattenedStruct {
4
                ho: 24,
4
                other: HashMap::new(),
4
                flat: Flattened { hi: 42 },
4
            },
4
            PrettyConfig::default()
4
        ),
4
        Err(Err(SpannedError {
4
            code: Error::InvalidValueForType {
4
                expected: String::from("i32"),
4
                found: String::from("the string \"Flattened\"")
4
            },
4
            position: Position { line: 5, col: 1 }
4
        }))
4
    );
4
}
#[test]
4
fn tagged_struct_beside_map_inside_flatten_struct_variant() {
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    #[serde(tag = "tag")]
    struct Flattened {
        hi: i32,
    }
24
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    enum FlattenedStructVariant {
        A {
            ho: i32,
            #[serde(flatten)]
            other: HashMap<String, i32>,
            #[serde(flatten)]
            flat: Flattened,
        },
    }
4
    assert_eq!(
4
        check_roundtrip(
4
            &FlattenedStructVariant::A {
4
                ho: 24,
4
                other: HashMap::new(),
4
                flat: Flattened { hi: 42 },
4
            },
4
            PrettyConfig::default()
4
        ),
4
        Err(Err(SpannedError {
4
            code: Error::InvalidValueForType {
4
                expected: String::from("i32"),
4
                found: String::from("the string \"Flattened\"")
4
            },
4
            position: Position { line: 5, col: 1 }
4
        }))
4
    );
4
}
#[test]
4
fn zero_length_untagged_tuple_variant() {
4
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    #[serde(untagged)]
    enum Untagged {
        A(),
    }
4
    assert_eq!(
4
        check_roundtrip(&Untagged::A(), PrettyConfig::default()),
4
        Err(Err(SpannedError {
4
            code: Error::Message(String::from(
4
                "data did not match any variant of untagged enum Untagged"
4
            )),
4
            position: Position { line: 1, col: 3 }
4
        }))
4
    );
4
}
#[test]
4
fn zero_length_untagged_struct_variant() {
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    #[serde(untagged)]
    enum Untagged {
        A {},
    }
4
    assert_eq!(
4
        check_roundtrip(&Untagged::A {}, PrettyConfig::default()),
4
        Err(Err(SpannedError {
4
            code: Error::Message(String::from(
4
                "data did not match any variant of untagged enum Untagged"
4
            )),
4
            position: Position { line: 1, col: 3 }
4
        }))
4
    );
4
}
#[test]
4
fn unwrapped_one_element_untagged_tuple_variant() {
    // A tuple variant with just one element that is not a newtype variant
8
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    #[serde(untagged)]
    enum Untagged {
        OneTuple(i32, #[serde(skip)] ()),
    }
4
    assert_eq!(
4
        check_roundtrip(&Untagged::OneTuple(42, ()), PrettyConfig::default()),
4
        Ok(())
4
    );
4
    assert_eq!(
4
        check_roundtrip(
4
            &Untagged::OneTuple(42, ()),
4
            PrettyConfig::default().extensions(Extensions::UNWRAP_VARIANT_NEWTYPES)
4
        ),
4
        Ok(())
4
    );
4
}
#[test]
4
fn unit_inside_untagged_newtype_variant_inside_internally_tagged_newtype_variant() {
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    #[serde(untagged)]
    enum Untagged {
        Newtype(()),
    }
4
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    #[serde(tag = "tag")]
    enum InternallyTagged {
        Newtype(Untagged),
    }
4
    assert_eq!(
4
        check_roundtrip(
4
            &InternallyTagged::Newtype(Untagged::Newtype(())),
4
            PrettyConfig::default()
4
        ),
4
        Err(Err(SpannedError {
4
            code: Error::Message(String::from(
4
                "data did not match any variant of untagged enum Untagged"
4
            )),
4
            position: Position { line: 3, col: 2 }
4
        }))
4
    );
4
}
#[test]
4
fn unit_inside_untagged_newtype_variant_inside_flatten_struct() {
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    #[serde(untagged)]
    enum Untagged {
        Newtype(()),
    }
8
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct FlattenedStruct {
        ho: i32,
        #[serde(flatten)]
        a: Untagged,
    }
4
    assert_eq!(
4
        check_roundtrip(
4
            &FlattenedStruct {
4
                ho: 24,
4
                a: Untagged::Newtype(()),
4
            },
4
            PrettyConfig::default()
4
        ),
4
        Err(Err(SpannedError {
4
            code: Error::Message(String::from(
4
                "data did not match any variant of untagged enum Untagged"
4
            )),
4
            position: Position { line: 3, col: 1 }
4
        }))
4
    );
4
}
#[test]
4
fn unit_struct_inside_untagged_newtype_variant_inside_internally_tagged_newtype_variant() {
4
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct Unit;
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    #[serde(untagged)]
    enum Untagged {
        Newtype(Unit),
    }
4
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    #[serde(tag = "tag")]
    enum InternallyTagged {
        Newtype(Untagged),
    }
4
    assert_eq!(
4
        check_roundtrip(
4
            &InternallyTagged::Newtype(Untagged::Newtype(Unit)),
4
            PrettyConfig::default()
4
        ),
4
        Err(Err(SpannedError {
4
            code: Error::Message(String::from(
4
                "data did not match any variant of untagged enum Untagged"
4
            )),
4
            position: Position { line: 3, col: 2 }
4
        }))
4
    );
4
}
#[test]
4
fn untagged_unit_variant_inside_internally_tagged_newtype_variant() {
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    #[serde(untagged)]
    enum Untagged {
        Unit,
    }
16
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    enum FlattenedStructVariant {
        C {
            ho: i32,
            #[serde(flatten)]
            a: Untagged,
        },
    }
4
    assert_eq!(
4
        check_roundtrip(
4
            &FlattenedStructVariant::C {
4
                ho: 24,
4
                a: Untagged::Unit,
4
            },
4
            PrettyConfig::default()
4
        ),
4
        Err(Err(SpannedError {
4
            code: Error::Message(String::from(
4
                "data did not match any variant of untagged enum Untagged"
4
            )),
4
            position: Position { line: 3, col: 1 }
4
        }))
4
    );
4
}
#[test]
4
fn untagged_unit_variant_inside_flatten_struct_variant() {
8
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    enum Enum {
        Unit,
    }
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    #[serde(untagged)]
    enum Untagged {
        Unit,
        Newtype(Enum),
    }
8
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    #[serde(tag = "tag")]
    enum InternallyTagged {
        Newtype(Untagged),
    }
4
    assert_eq!(
4
        check_roundtrip(
4
            &InternallyTagged::Newtype(Untagged::Newtype(Enum::Unit)),
4
            PrettyConfig::default()
4
        ),
4
        Ok(())
4
    );
4
    assert_eq!(
4
        check_roundtrip(
4
            &InternallyTagged::Newtype(Untagged::Unit),
4
            PrettyConfig::default()
4
        ),
4
        Err(Err(SpannedError {
4
            code: Error::Message(String::from(
4
                "data did not match any variant of untagged enum Untagged"
4
            )),
4
            position: Position { line: 3, col: 2 }
4
        }))
4
    );
4
}
#[test]
4
fn unit_inside_internally_tagged_newtype_variant_inside_multi_flatten_struct() {
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct AnotherFlattenedStruct {
        hi: i32,
    }
4
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    #[serde(tag = "tag")]
    enum InternallyTagged {
        Newtype(()),
    }
16
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct FlattenedStruct {
        ho: i32,
        #[serde(flatten)]
        a: InternallyTagged,
        #[serde(flatten)]
        b: AnotherFlattenedStruct,
    }
4
    assert_eq!(
4
        check_roundtrip(
4
            &FlattenedStruct {
4
                ho: 24,
4
                a: InternallyTagged::Newtype(()),
4
                b: AnotherFlattenedStruct { hi: 42 },
4
            },
4
            PrettyConfig::default()
4
        ),
4
        Err(Err(SpannedError {
4
            code: Error::InvalidValueForType {
4
                expected: String::from("unit"),
4
                found: String::from("a map")
4
            },
4
            position: Position { line: 5, col: 1 }
4
        }))
4
    );
4
}
#[test]
4
fn untagged_unit_variant_inside_internally_tagged_newtype_variant_inside_multi_flatten_struct() {
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    #[serde(untagged)]
    enum Untagged {
        Unit,
    }
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct AnotherFlattenedStruct {
        hi: i32,
    }
4
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    #[serde(tag = "tag")]
    enum InternallyTagged {
        Newtype(Untagged),
    }
16
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct FlattenedStruct {
        ho: i32,
        #[serde(flatten)]
        a: InternallyTagged,
        #[serde(flatten)]
        b: AnotherFlattenedStruct,
    }
4
    assert_eq!(
4
        check_roundtrip(
4
            &FlattenedStruct {
4
                ho: 24,
4
                a: InternallyTagged::Newtype(Untagged::Unit),
4
                b: AnotherFlattenedStruct { hi: 42 },
4
            },
4
            PrettyConfig::default()
4
        ),
4
        Err(Err(SpannedError {
4
            code: Error::Message(String::from(
4
                "data did not match any variant of untagged enum Untagged"
4
            )),
4
            position: Position { line: 5, col: 1 }
4
        }))
4
    );
4
}
#[test]
4
fn flattened_externally_tagged_newtype_variant_beside_flattened_intenally_tagged_enum() {
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    enum ExternallyTagged {
        Newtype(()),
        Other(()),
    }
4
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    #[serde(tag = "tag")]
    enum InternallyTagged {
        Newtype(ExternallyTagged),
    }
4
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct Flattened {
        #[serde(flatten)]
        a: InternallyTagged,
        #[serde(flatten)]
        b: ExternallyTagged,
    }
4
    assert_eq!(
4
        check_roundtrip(
4
            &Flattened {
4
                a: InternallyTagged::Newtype(ExternallyTagged::Other(())),
4
                b: ExternallyTagged::Newtype(()),
4
            },
4
            PrettyConfig::default()
4
        ),
4
        Err(Err(SpannedError {
4
            code: Error::InvalidValueForType {
4
                expected: String::from("map with a single key"),
4
                found: String::from("a map"),
4
            },
4
            position: Position { line: 5, col: 1 }
4
        }))
4
    );
4
}
#[test]
4
fn flattened_externally_tagged_struct_variant_beside_flattened_intenally_tagged_enum() {
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    enum ExternallyTagged {
        Struct { a: i32 },
        Other(()),
    }
4
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    #[serde(tag = "tag")]
    enum InternallyTagged {
        Newtype(ExternallyTagged),
    }
4
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct Flattened {
        #[serde(flatten)]
        a: InternallyTagged,
        #[serde(flatten)]
        b: ExternallyTagged,
    }
4
    assert_eq!(
4
        check_roundtrip(
4
            &Flattened {
4
                a: InternallyTagged::Newtype(ExternallyTagged::Other(())),
4
                b: ExternallyTagged::Struct { a: 42 },
4
            },
4
            PrettyConfig::default()
4
        ),
4
        Err(Err(SpannedError {
4
            code: Error::InvalidValueForType {
4
                expected: String::from("map with a single key"),
4
                found: String::from("a map"),
4
            },
4
            position: Position { line: 7, col: 1 }
4
        }))
4
    );
4
}
#[test]
4
fn flattened_map_inside_option_beside_flattened_struct_variant() {
12
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    #[serde(untagged)]
    enum Untagged {
        Struct { a: i32 },
    }
4
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct Flattened {
        #[serde(flatten)]
        a: Untagged,
        #[serde(flatten)]
        b: Option<BTreeMap<String, i32>>,
    }
4
    assert_eq!(
4
        check_roundtrip(
4
            &Flattened {
4
                a: Untagged::Struct {
4
                    a: 42,
4
                },
4
                b: Some([(String::from("b"), 24)].into_iter().collect()),
4
            },
4
            PrettyConfig::default()
4
        ),
4
        Err(Ok(Error::Message(String::from("ROUNDTRIP error: Flattened { a: Struct { a: 42 }, b: Some({\"b\": 24}) } != Flattened { a: Struct { a: 42 }, b: Some({\"a\": 42, \"b\": 24}) }"))))
4
    );
4
}
#[test]
4
fn flattened_untagged_struct_beside_flattened_untagged_struct() {
24
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    #[serde(untagged)]
    enum Untagged {
        Struct { a: i32 },
        Other { b: i32 },
    }
4
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct Flattened {
        #[serde(flatten)]
        a: Untagged,
        #[serde(flatten)]
        b: Untagged,
    }
4
    assert_eq!(
4
        check_roundtrip(
4
            &Flattened {
4
                a: Untagged::Struct {
4
                    a: 42,
4
                },
4
                b: Untagged::Other {
4
                    b: 24,
4
                },
4
            },
4
            PrettyConfig::default()
4
        ),
4
        Err(Ok(Error::Message(String::from("ROUNDTRIP error: Flattened { a: Struct { a: 42 }, b: Other { b: 24 } } != Flattened { a: Struct { a: 42 }, b: Struct { a: 42 } }"))))
4
    );
4
}
#[test]
4
fn flattened_field_inside_flattened_struct_alongside_map() {
12
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct Units {
        a: i32,
        #[serde(flatten)]
        b: (),
    }
4
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct Flattened {
        #[serde(flatten)]
        a: Units,
        #[serde(flatten)]
        b: BTreeMap<String, i32>,
    }
4
    assert_eq!(
4
        check_roundtrip(
4
            &Flattened {
4
                a: Units {
4
                    a: 42,
4
                    b: (),
4
                },
4
                b: [(String::from("c"), 24)].into_iter().collect(),
4
            },
4
            PrettyConfig::default()
4
        ),
4
        Err(Ok(Error::Message(String::from("ROUNDTRIP error: Flattened { a: Units { a: 42, b: () }, b: {\"c\": 24} } != Flattened { a: Units { a: 42, b: () }, b: {\"a\": 42, \"c\": 24} }"))))
4
    );
4
}
376
fn check_roundtrip<T: PartialEq + std::fmt::Debug + Serialize + serde::de::DeserializeOwned>(
376
    val: &T,
376
    config: PrettyConfig,
376
) -> Result<(), Result<Error, SpannedError>> {
376
    let ron = ron::ser::to_string_pretty(val, config).map_err(|err| Ok(err))?;
366
    println!("{ron}");
366
    let de = ron::from_str(&ron).map_err(|err| Err(err))?;
142
    if val == &de {
94
        Ok(())
    } else {
48
        Err(Ok(Error::Message(format!(
48
            "ROUNDTRIP error: {:?} != {:?}",
48
            val, de
48
        ))))
    }
376
}