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

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

            
9
#[test]
10
4
fn struct_names_inside_internally_tagged() {
11
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
12
    struct A {
13
        hi: i32,
14
    }
15

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

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

            
53
#[test]
54
4
fn struct_names_inside_adjacently_tagged() {
55
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
56
    struct A {
57
        hi: i32,
58
    }
59

            
60
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
61
    #[serde(tag = "tag", content = "content")]
62
    enum AdjacentlyTagged {
63
        B { ho: i32, a: A },
64
    }
65

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

            
112
#[test]
113
4
fn struct_names_inside_untagged() {
114
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
115
    struct A {
116
        hi: i32,
117
    }
118

            
119
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
120
    #[serde(untagged)]
121
    enum Untagged {
122
        B { ho: i32, a: A },
123
    }
124

            
125
4
    assert_eq!(
126
4
        check_roundtrip(
127
4
            &Untagged::B {
128
4
                ho: 24,
129
4
                a: A { hi: 42 }
130
4
            },
131
4
            PrettyConfig::default()
132
        ),
133
        Ok(())
134
    );
135
4
    assert_eq!(
136
4
        check_roundtrip(
137
4
            &Untagged::B {
138
4
                ho: 24,
139
4
                a: A { hi: 42 }
140
4
            },
141
4
            PrettyConfig::default().struct_names(true)
142
        ),
143
4
        Err(Err(SpannedError {
144
4
            code: Error::Message(String::from(
145
4
                "data did not match any variant of untagged enum Untagged"
146
4
            )),
147
4
            span: Span {
148
4
                start: Position { line: 6, col: 1 },
149
4
                end: Position { line: 6, col: 2 }
150
4
            }
151
4
        })),
152
    );
153
4
}
154

            
155
#[test]
156
4
fn struct_names_inside_flatten_struct() {
157
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
158
    struct A {
159
        hi: i32,
160
    }
161

            
162
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
163
    struct B {
164
        a: A,
165
    }
166

            
167
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
168
    struct FlattenedStruct {
169
        ho: i32,
170
        #[serde(flatten)]
171
        a: B,
172
    }
173

            
174
4
    assert_eq!(
175
4
        check_roundtrip(
176
4
            &FlattenedStruct {
177
4
                ho: 24,
178
4
                a: B { a: A { hi: 42 } }
179
4
            },
180
4
            PrettyConfig::default()
181
        ),
182
        Ok(())
183
    );
184
4
    assert_eq!(
185
4
        check_roundtrip(
186
4
            &FlattenedStruct {
187
4
                ho: 24,
188
4
                a: B { a: A { hi: 42 } }
189
4
            },
190
4
            PrettyConfig::default().struct_names(true)
191
        ),
192
        Err(Err(SpannedError {
193
            code: Error::MissingStructField {
194
                field: "hi",
195
                outer: None
196
            },
197
            span: Span {
198
                start: Position { line: 6, col: 1 },
199
                end: Position { line: 6, col: 1 }
200
            }
201
        })),
202
    );
203
4
}
204

            
205
#[test]
206
4
fn struct_names_inside_flatten_struct_variant() {
207
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
208
    struct A {
209
        hi: i32,
210
    }
211

            
212
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
213
    struct B {
214
        a: A,
215
    }
216

            
217
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
218
    enum FlattenedStructVariant {
219
        C {
220
            ho: i32,
221
            #[serde(flatten)]
222
            a: B,
223
        },
224
    }
225

            
226
4
    assert_eq!(
227
4
        check_roundtrip(
228
4
            &FlattenedStructVariant::C {
229
4
                ho: 24,
230
4
                a: B { a: A { hi: 42 } }
231
4
            },
232
4
            PrettyConfig::default()
233
        ),
234
        Ok(())
235
    );
236
4
    assert_eq!(
237
4
        check_roundtrip(
238
4
            &FlattenedStructVariant::C {
239
4
                ho: 24,
240
4
                a: B { a: A { hi: 42 } }
241
4
            },
242
4
            PrettyConfig::default().struct_names(true)
243
        ),
244
4
        Err(Err(SpannedError {
245
4
            code: Error::MissingStructField {
246
4
                field: "hi",
247
4
                outer: Some(String::from("C"))
248
4
            },
249
4
            span: Span {
250
4
                start: Position { line: 6, col: 1 },
251
4
                end: Position { line: 6, col: 1 }
252
4
            }
253
4
        })),
254
    );
255
4
}
256

            
257
#[test]
258
4
fn implicit_some_inside_internally_tagged() {
259
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
260
    struct A {
261
        hi: Option<Option<()>>,
262
    }
263

            
264
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
265
    #[serde(tag = "tag")]
266
    enum InternallyTagged {
267
        B { ho: i32, a: A },
268
    }
269

            
270
4
    assert_eq!(
271
4
        check_roundtrip(
272
4
            &InternallyTagged::B {
273
4
                ho: 24,
274
4
                a: A { hi: Some(Some(())) }
275
4
            },
276
4
            PrettyConfig::default()
277
        ),
278
        Ok(())
279
    );
280
4
    assert_eq!(
281
4
        check_roundtrip(
282
4
            &InternallyTagged::B {
283
4
                ho: 24,
284
4
                a: A { hi: Some(Some(())) }
285
4
            },
286
4
            PrettyConfig::default().extensions(Extensions::IMPLICIT_SOME)
287
        ),
288
4
        Err(Ok(Error::Message(String::from("ROUNDTRIP error: B { ho: 24, a: A { hi: Some(Some(())) } } != B { ho: 24, a: A { hi: None } }"))))
289
    );
290
4
}
291

            
292
#[test]
293
4
fn implicit_some_inside_adjacently_tagged() {
294
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
295
    struct Unit;
296

            
297
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
298
    struct A {
299
        hi: Option<Option<Unit>>,
300
    }
301

            
302
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
303
    #[serde(tag = "tag", content = "content")]
304
    enum AdjacentlyTagged {
305
        B { ho: i32, a: A },
306
    }
307

            
308
4
    assert_eq!(
309
4
        check_roundtrip(
310
4
            &AdjacentlyTagged::B {
311
4
                ho: 24,
312
4
                a: A {
313
4
                    hi: Some(Some(Unit))
314
4
                }
315
4
            },
316
4
            PrettyConfig::default()
317
        ),
318
        Ok(())
319
    );
320
4
    assert_eq!(
321
4
        check_roundtrip(
322
4
            &AdjacentlyTagged::B {
323
4
                ho: 24,
324
4
                a: A {
325
4
                    hi: Some(Some(Unit))
326
4
                }
327
4
            },
328
4
            PrettyConfig::default().extensions(Extensions::IMPLICIT_SOME)
329
        ),
330
        Ok(()),
331
    );
332
4
    assert_eq!(
333
4
        ron::from_str::<AdjacentlyTagged>(
334
4
            "#![enable(implicit_some)] (tag: B, content: (ho: 24, a: A(hi: ())))"
335
        ),
336
        Ok(AdjacentlyTagged::B {
337
            ho: 24,
338
            a: A {
339
                hi: Some(Some(Unit))
340
            }
341
        }),
342
    );
343
4
    assert_eq!(
344
4
        ron::from_str::<AdjacentlyTagged>(
345
4
            "#![enable(implicit_some)] (content: (ho: 24, a: A(hi: ())), tag: B)"
346
        ),
347
        Ok(AdjacentlyTagged::B {
348
            ho: 24,
349
            a: A { hi: None } // THIS IS WRONG
350
        }),
351
    );
352
4
}
353

            
354
#[test]
355
4
fn implicit_some_inside_untagged() {
356
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
357
    struct A {
358
        hi: Option<Option<()>>,
359
    }
360

            
361
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
362
    #[serde(untagged)]
363
    enum Untagged {
364
        B { ho: i32, a: A },
365
    }
366

            
367
4
    assert_eq!(
368
4
        check_roundtrip(
369
4
            &Untagged::B {
370
4
                ho: 24,
371
4
                a: A { hi: Some(Some(())) }
372
4
            },
373
4
            PrettyConfig::default()
374
        ),
375
        Ok(())
376
    );
377
4
    assert_eq!(
378
4
        check_roundtrip(
379
4
            &Untagged::B {
380
4
                ho: 24,
381
4
                a: A { hi: Some(Some(())) }
382
4
            },
383
4
            PrettyConfig::default().extensions(Extensions::IMPLICIT_SOME)
384
        ),
385
4
        Err(Ok(Error::Message(String::from(
386
4
            "ROUNDTRIP error: B { ho: 24, a: A { hi: Some(Some(())) } } != B { ho: 24, a: A { hi: None } }"
387
4
        )))),
388
    );
389
4
}
390

            
391
#[test]
392
4
fn implicit_some_inside_flatten_struct() {
393
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
394
    #[serde(untagged)]
395
    enum Untagged {
396
        Unit,
397
    }
398

            
399
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
400
    struct A {
401
        hi: Option<Option<Untagged>>,
402
    }
403

            
404
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
405
    struct B {
406
        a: A,
407
    }
408

            
409
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
410
    struct FlattenedStruct {
411
        ho: i32,
412
        #[serde(flatten)]
413
        a: B,
414
    }
415

            
416
4
    assert_eq!(
417
4
        check_roundtrip(
418
4
            &FlattenedStruct {
419
4
                ho: 24,
420
4
                a: B {
421
4
                    a: A {
422
4
                        hi: Some(Some(Untagged::Unit))
423
4
                    }
424
4
                }
425
4
            },
426
4
            PrettyConfig::default()
427
        ),
428
        Ok(())
429
    );
430
4
    assert_eq!(
431
4
        check_roundtrip(
432
4
            &FlattenedStruct {
433
4
                ho: 24,
434
4
                a: B {
435
4
                    a: A { hi: Some(Some(Untagged::Unit)) }
436
4
                }
437
4
            },
438
4
            PrettyConfig::default().extensions(Extensions::IMPLICIT_SOME)
439
        ),
440
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 } } }"))))
441
    );
442
4
}
443

            
444
#[test]
445
4
fn implicit_some_inside_flatten_struct_variant() {
446
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
447
    struct A {
448
        hi: Option<Option<[u8; 0]>>,
449
    }
450

            
451
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
452
    struct B {
453
        a: A,
454
    }
455

            
456
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
457
    enum FlattenedStructVariant {
458
        C {
459
            ho: i32,
460
            #[serde(flatten)]
461
            a: B,
462
        },
463
    }
464

            
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()
474
        ),
475
4
        Err(Err(SpannedError {
476
4
            code: Error::InvalidValueForType {
477
4
                expected: String::from("an empty array"),
478
4
                found: String::from("a unit value")
479
4
            },
480
4
            span: Span {
481
4
                start: Position { line: 6, col: 1 },
482
4
                end: Position { line: 6, col: 1 }
483
4
            }
484
4
        }))
485
    );
486
4
    assert_eq!(
487
4
        check_roundtrip(
488
4
            &FlattenedStructVariant::C {
489
4
                ho: 24,
490
4
                a: B {
491
4
                    a: A { hi: Some(Some([])) }
492
4
                }
493
4
            },
494
4
            PrettyConfig::default().extensions(Extensions::IMPLICIT_SOME)
495
        ),
496
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 } } }"))))
497
    );
498
4
}
499

            
500
#[test]
501
4
fn newtype_inside_internally_tagged() {
502
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
503
    struct A(i32);
504

            
505
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
506
    #[serde(tag = "tag")]
507
    enum InternallyTagged {
508
        B { ho: i32, a: A },
509
    }
510

            
511
    // NOTE:
512
    // 1. ron is correctly collected into Content, newtype is a one-seq here
513
    // 2. newtype asks ContentDeserializer for newtype
514
    // 3. ContentDeserializer forwards any value to visit_newtype_struct
515
    //    https://github.com/serde-rs/serde/blob/8c4aad3a59515f7b779f764d5e16d6bae297ab7f/serde/src/private/de.rs#L1347-L1359
516

            
517
4
    assert_eq!(
518
4
        check_roundtrip(
519
4
            &InternallyTagged::B { ho: 24, a: A(42) },
520
4
            PrettyConfig::default()
521
        ),
522
4
        Err(Err(SpannedError {
523
4
            code: Error::InvalidValueForType {
524
4
                expected: String::from("i32"),
525
4
                found: String::from("a sequence")
526
4
            },
527
4
            span: Span {
528
4
                start: Position { line: 5, col: 1 },
529
4
                end: Position { line: 5, col: 2 }
530
4
            }
531
4
        }))
532
    );
533
4
}
534

            
535
#[test]
536
4
fn newtype_inside_adjacently_tagged() {
537
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
538
    struct A(i32);
539

            
540
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
541
    #[serde(tag = "tag", content = "content")]
542
    enum AdjacentlyTagged {
543
        B { ho: i32, a: A },
544
    }
545

            
546
4
    assert_eq!(
547
4
        check_roundtrip(
548
4
            &AdjacentlyTagged::B { ho: 24, a: A(42) },
549
4
            PrettyConfig::default()
550
        ),
551
        Ok(())
552
    );
553
4
    assert_eq!(
554
4
        ron::from_str::<AdjacentlyTagged>("(tag: B, content: (ho: 24, a: (42)))"),
555
        Ok(AdjacentlyTagged::B { ho: 24, a: A(42) }),
556
    );
557
4
    assert_eq!(
558
4
        ron::from_str::<AdjacentlyTagged>("(content: (ho: 24, a: (42)), tag: B)"),
559
4
        Err(SpannedError {
560
4
            code: Error::InvalidValueForType {
561
4
                expected: String::from("i32"),
562
4
                found: String::from("a sequence")
563
4
            },
564
4
            span: Span {
565
4
                start: Position { line: 1, col: 36 },
566
4
                end: Position { line: 1, col: 36 }
567
4
            }
568
4
        })
569
    );
570
4
}
571

            
572
#[test]
573
4
fn newtype_inside_untagged() {
574
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
575
    struct A(i32);
576

            
577
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
578
    #[serde(untagged)]
579
    enum Untagged {
580
        B { ho: i32, a: A },
581
    }
582

            
583
4
    assert_eq!(
584
4
        check_roundtrip(&Untagged::B { ho: 24, a: A(42) }, PrettyConfig::default()),
585
4
        Err(Err(SpannedError {
586
4
            code: Error::Message(String::from(
587
4
                "data did not match any variant of untagged enum Untagged"
588
4
            )),
589
4
            span: Span {
590
4
                start: Position { line: 4, col: 1 },
591
4
                end: Position { line: 4, col: 2 }
592
4
            }
593
4
        }))
594
    );
595
4
}
596

            
597
#[test]
598
4
fn newtype_inside_flatten_struct() {
599
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
600
    struct A(i32);
601

            
602
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
603
    struct B {
604
        a: A,
605
    }
606

            
607
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
608
    struct FlattenedStruct {
609
        ho: i32,
610
        #[serde(flatten)]
611
        a: B,
612
    }
613

            
614
4
    assert_eq!(
615
4
        check_roundtrip(
616
4
            &FlattenedStruct {
617
4
                ho: 24,
618
4
                a: B { a: A(42) }
619
4
            },
620
4
            PrettyConfig::default()
621
        ),
622
4
        Err(Err(SpannedError {
623
4
            code: Error::InvalidValueForType {
624
4
                expected: String::from("i32"),
625
4
                found: String::from("a sequence")
626
4
            },
627
4
            span: Span {
628
4
                start: Position { line: 4, col: 1 },
629
4
                end: Position { line: 4, col: 1 }
630
4
            }
631
4
        }))
632
    );
633
4
}
634

            
635
#[test]
636
4
fn newtype_inside_flatten_struct_variant() {
637
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
638
    struct A(i32);
639

            
640
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
641
    struct B {
642
        a: A,
643
    }
644

            
645
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
646
    enum FlattenedStructVariant {
647
        C {
648
            ho: i32,
649
            #[serde(flatten)]
650
            a: B,
651
        },
652
    }
653

            
654
4
    assert_eq!(
655
4
        check_roundtrip(
656
4
            &FlattenedStructVariant::C {
657
4
                ho: 24,
658
4
                a: B { a: A(42) }
659
4
            },
660
4
            PrettyConfig::default()
661
        ),
662
4
        Err(Err(SpannedError {
663
4
            code: Error::InvalidValueForType {
664
4
                expected: String::from("i32"),
665
4
                found: String::from("a sequence")
666
4
            },
667
4
            span: Span {
668
4
                start: Position { line: 4, col: 1 },
669
4
                end: Position { line: 4, col: 1 }
670
4
            }
671
4
        }))
672
    );
673
4
}
674

            
675
#[test]
676
4
fn one_tuple_inside_unwrapped_newtype_variant_inside_internally_tagged() {
677
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
678
    enum A {
679
        Newtype((i32,)),
680
    }
681

            
682
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
683
    #[serde(tag = "tag")]
684
    enum InternallyTagged {
685
        B { ho: i32, a: A },
686
    }
687

            
688
4
    assert_eq!(
689
4
        check_roundtrip(
690
4
            &InternallyTagged::B {
691
4
                ho: 24,
692
4
                a: A::Newtype((42,))
693
4
            },
694
4
            PrettyConfig::default()
695
        ),
696
        Ok(())
697
    );
698
4
    assert_eq!(
699
4
        check_roundtrip(
700
4
            &InternallyTagged::B {
701
4
                ho: 24,
702
4
                a: A::Newtype((42,))
703
4
            },
704
4
            PrettyConfig::default().extensions(Extensions::UNWRAP_VARIANT_NEWTYPES)
705
        ),
706
4
        Err(Err(SpannedError {
707
4
            code: Error::InvalidValueForType {
708
4
                expected: String::from("a tuple of size 1"),
709
4
                found: String::from("the unsigned integer `42`")
710
4
            },
711
4
            span: Span {
712
4
                start: Position { line: 6, col: 1 },
713
4
                end: Position { line: 6, col: 2 }
714
4
            }
715
4
        }))
716
    );
717
4
}
718

            
719
#[test]
720
4
fn one_tuple_inside_unwrapped_newtype_variant_inside_adjacently_tagged() {
721
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
722
    enum A {
723
        Newtype([i32; 1]),
724
    }
725

            
726
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
727
    #[serde(tag = "tag", content = "content")]
728
    enum AdjacentlyTagged {
729
        B { ho: i32, a: A },
730
    }
731

            
732
4
    assert_eq!(
733
4
        check_roundtrip(
734
4
            &AdjacentlyTagged::B {
735
4
                ho: 24,
736
4
                a: A::Newtype([42])
737
4
            },
738
4
            PrettyConfig::default()
739
        ),
740
        Ok(())
741
    );
742
4
    assert_eq!(
743
4
        check_roundtrip(
744
4
            &AdjacentlyTagged::B {
745
4
                ho: 24,
746
4
                a: A::Newtype([42])
747
4
            },
748
4
            PrettyConfig::default().extensions(Extensions::UNWRAP_VARIANT_NEWTYPES)
749
        ),
750
        Ok(())
751
    );
752
4
    assert_eq!(
753
4
        ron::from_str::<AdjacentlyTagged>(
754
4
            "#![enable(unwrap_variant_newtypes)] (tag: B, content: (ho: 24, a: Newtype(42)))"
755
        ),
756
        Ok(AdjacentlyTagged::B {
757
            ho: 24,
758
            a: A::Newtype([42])
759
        }),
760
    );
761
4
    assert_eq!(
762
4
        ron::from_str::<AdjacentlyTagged>(
763
4
            "#![enable(unwrap_variant_newtypes)] (content: (ho: 24, a: Newtype(42)), tag: B)"
764
        ),
765
4
        Err(SpannedError {
766
4
            code: Error::InvalidValueForType {
767
4
                expected: String::from("an array of length 1"),
768
4
                found: String::from("the unsigned integer `42`")
769
4
            },
770
4
            span: Span {
771
4
                start: Position { line: 1, col: 79 },
772
4
                end: Position { line: 1, col: 79 }
773
4
            }
774
4
        })
775
    );
776
4
}
777

            
778
#[test]
779
4
fn one_tuple_inside_unwrapped_newtype_variant_inside_untagged() {
780
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
781
    struct OneTuple(i32, #[serde(skip)] ());
782

            
783
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
784
    #[serde(untagged)]
785
    enum Untagged {
786
        B { ho: i32, a: Option<OneTuple> },
787
    }
788

            
789
4
    assert_eq!(
790
4
        check_roundtrip(
791
4
            &Untagged::B {
792
4
                ho: 24,
793
4
                a: Some(OneTuple(42, ()))
794
4
            },
795
4
            PrettyConfig::default()
796
        ),
797
        Ok(())
798
    );
799
4
    assert_eq!(
800
4
        check_roundtrip(
801
4
            &Untagged::B {
802
4
                ho: 24,
803
4
                a: Some(OneTuple(42, ()))
804
4
            },
805
4
            PrettyConfig::default().extensions(Extensions::UNWRAP_VARIANT_NEWTYPES)
806
        ),
807
4
        Err(Err(SpannedError {
808
4
            code: Error::Message(String::from(
809
4
                "data did not match any variant of untagged enum Untagged"
810
4
            )),
811
4
            span: Span {
812
4
                start: Position { line: 5, col: 1 },
813
4
                end: Position { line: 5, col: 2 }
814
4
            }
815
4
        }))
816
    );
817
4
}
818

            
819
#[test]
820
4
fn one_tuple_inside_unwrapped_newtype_variant_inside_flatten_struct() {
821
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
822
    enum A {
823
        Newtype([i32; 1]),
824
    }
825

            
826
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
827
    struct B {
828
        a: A,
829
    }
830

            
831
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
832
    struct FlattenedStruct {
833
        ho: i32,
834
        #[serde(flatten)]
835
        a: B,
836
    }
837

            
838
4
    assert_eq!(
839
4
        check_roundtrip(
840
4
            &FlattenedStruct {
841
4
                ho: 24,
842
4
                a: B {
843
4
                    a: A::Newtype([42])
844
4
                }
845
4
            },
846
4
            PrettyConfig::default()
847
        ),
848
        Ok(())
849
    );
850
4
    assert_eq!(
851
4
        check_roundtrip(
852
4
            &FlattenedStruct {
853
4
                ho: 24,
854
4
                a: B {
855
4
                    a: A::Newtype([42])
856
4
                }
857
4
            },
858
4
            PrettyConfig::default().extensions(Extensions::UNWRAP_VARIANT_NEWTYPES)
859
        ),
860
4
        Err(Err(SpannedError {
861
4
            code: Error::InvalidValueForType {
862
4
                expected: String::from("an array of length 1"),
863
4
                found: String::from("the unsigned integer `42`")
864
4
            },
865
4
            span: Span {
866
4
                start: Position { line: 5, col: 1 },
867
4
                end: Position { line: 5, col: 1 }
868
4
            }
869
4
        }))
870
    );
871
4
}
872

            
873
#[test]
874
4
fn one_tuple_inside_unwrapped_newtype_variant_inside_flatten_struct_variant() {
875
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
876
    enum A {
877
        Newtype((i32,)),
878
    }
879

            
880
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
881
    struct B {
882
        a: A,
883
    }
884

            
885
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
886
    enum FlattenedStructVariant {
887
        C {
888
            ho: i32,
889
            #[serde(flatten)]
890
            a: B,
891
        },
892
    }
893

            
894
4
    assert_eq!(
895
4
        check_roundtrip(
896
4
            &FlattenedStructVariant::C {
897
4
                ho: 24,
898
4
                a: B {
899
4
                    a: A::Newtype((42,))
900
4
                }
901
4
            },
902
4
            PrettyConfig::default()
903
        ),
904
        Ok(()),
905
    );
906
4
    assert_eq!(
907
4
        check_roundtrip(
908
4
            &FlattenedStructVariant::C {
909
4
                ho: 24,
910
4
                a: B {
911
4
                    a: A::Newtype((42,))
912
4
                }
913
4
            },
914
4
            PrettyConfig::default().extensions(Extensions::UNWRAP_VARIANT_NEWTYPES)
915
        ),
916
4
        Err(Err(SpannedError {
917
4
            code: Error::InvalidValueForType {
918
4
                expected: String::from("a tuple of size 1"),
919
4
                found: String::from("the unsigned integer `42`")
920
4
            },
921
4
            span: Span {
922
4
                start: Position { line: 5, col: 1 },
923
4
                end: Position { line: 5, col: 1 }
924
4
            }
925
4
        }))
926
    );
927
4
}
928

            
929
#[test]
930
4
fn one_tuple_variant_inside_internally_tagged() {
931
    // A tuple variant with just one element that is not a newtype variant
932
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
933
    enum OneEnum {
934
        OneTuple(i32, #[serde(skip)] ()),
935
    }
936

            
937
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
938
    struct A {
939
        hi: OneEnum,
940
    }
941

            
942
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
943
    #[serde(tag = "tag")]
944
    enum InternallyTagged {
945
        B { ho: i32, a: A },
946
    }
947

            
948
4
    assert_eq!(
949
4
        check_roundtrip(
950
4
            &InternallyTagged::B {
951
4
                ho: 24,
952
4
                a: A {
953
4
                    hi: OneEnum::OneTuple(42, ())
954
4
                }
955
4
            },
956
4
            PrettyConfig::default()
957
        ),
958
4
        Err(Err(SpannedError {
959
4
            code: Error::InvalidValueForType {
960
4
                expected: String::from("tuple variant"),
961
4
                found: String::from("the unsigned integer `42`")
962
4
            },
963
4
            span: Span {
964
4
                start: Position { line: 7, col: 1 },
965
4
                end: Position { line: 7, col: 2 }
966
4
            }
967
4
        }))
968
    );
969
4
}
970

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

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

            
984
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
985
    #[serde(tag = "tag", content = "content")]
986
    enum AdjacentlyTagged {
987
        B { ho: i32, a: A },
988
    }
989

            
990
4
    assert_eq!(
991
4
        check_roundtrip(
992
4
            &AdjacentlyTagged::B {
993
4
                ho: 24,
994
4
                a: A {
995
4
                    hi: OneEnum::OneTuple(42, ())
996
4
                }
997
4
            },
998
4
            PrettyConfig::default()
999
        ),
        Ok(())
    );
4
    assert_eq!(
4
        ron::from_str::<AdjacentlyTagged>("(tag: B, content: (ho: 24, a: (hi: OneTuple(42))))"),
        Ok(AdjacentlyTagged::B {
            ho: 24,
            a: A {
                hi: OneEnum::OneTuple(42, ())
            }
        }),
    );
4
    assert_eq!(
4
        ron::from_str::<AdjacentlyTagged>("(content: (ho: 24, a: (hi: OneTuple(42))), tag: B)"),
4
        Err(SpannedError {
4
            code: Error::InvalidValueForType {
4
                expected: String::from("tuple variant"),
4
                found: String::from("the unsigned integer `42`")
4
            },
4
            span: Span {
4
                start: Position { line: 1, col: 50 },
4
                end: Position { line: 1, col: 50 }
4
            }
4
        })
    );
4
}
#[test]
4
fn one_tuple_variant_inside_untagged() {
    // A tuple variant with just one element that is not a newtype variant
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    enum OneEnum {
        OneTuple(i32, #[serde(skip)] ()),
    }
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct A {
        hi: OneEnum,
    }
    #[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: OneEnum::OneTuple(42, ())
4
                }
4
            },
4
            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
            span: Span {
4
                start: Position { line: 6, col: 1 },
4
                end: 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
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    enum OneEnum {
        OneTuple(i32, #[serde(skip)] ()),
    }
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct A {
        hi: OneEnum,
    }
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct B {
        a: A,
    }
    #[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
        Err(Err(SpannedError {
4
            code: Error::InvalidValueForType {
4
                expected: String::from("tuple variant"),
4
                found: String::from("the unsigned integer `42`")
4
            },
4
            span: Span {
4
                start: Position { line: 6, col: 1 },
4
                end: 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
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    enum OneEnum {
        OneTuple(i32, #[serde(skip)] ()),
    }
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct A {
        hi: OneEnum,
    }
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct B {
        a: A,
    }
    #[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
        Err(Err(SpannedError {
4
            code: Error::InvalidValueForType {
4
                expected: String::from("tuple variant"),
4
                found: String::from("the unsigned integer `42`")
4
            },
4
            span: Span {
4
                start: Position { line: 6, col: 1 },
4
                end: Position { line: 6, col: 1 }
4
            }
4
        }))
    );
4
}
#[test]
4
fn raw_value_inside_internally_tagged() {
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct A {
        hi: Box<ron::value::RawValue>,
    }
    #[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
        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
            span: Span {
4
                start: Position { line: 7, col: 1 },
4
                end: Position { line: 7, col: 2 }
4
            }
4
        }))
    );
4
}
#[test]
4
fn raw_value_inside_adjacently_tagged() {
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct A {
        hi: Box<ron::value::RawValue>,
    }
    #[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()
        ),
        // 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
    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
    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
            span: Span {
4
                start: Position { line: 1, col: 39 },
4
                end: Position { line: 1, col: 39 }
4
            }
4
        })
    );
4
}
#[test]
4
fn raw_value_inside_untagged() {
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct A {
        hi: Box<ron::value::RawValue>,
    }
    #[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
        Err(Err(SpannedError {
4
            code: Error::Message(String::from(
4
                "data did not match any variant of untagged enum Untagged"
4
            )),
4
            span: Span {
4
                start: Position { line: 6, col: 1 },
4
                end: Position { line: 6, col: 2 }
4
            }
4
        }))
    );
4
}
#[test]
4
fn raw_value_inside_flatten_struct() {
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct A {
        hi: Box<ron::value::RawValue>,
    }
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct B {
        a: A,
    }
    #[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
        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
            span: Span {
4
                start: Position { line: 6, col: 1 },
4
                end: Position { line: 6, col: 1 }
4
            }
4
        }))
    );
4
}
#[test]
4
fn raw_value_inside_flatten_struct_variant() {
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct A {
        hi: Box<ron::value::RawValue>,
    }
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct B {
        a: A,
    }
    #[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
        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
            span: Span {
4
                start: Position { line: 6, col: 1 },
4
                end: Position { line: 6, col: 1 }
4
            }
4
        }))
    );
4
}
#[test]
4
fn unit_like_zero_length_inside_internally_tagged() {
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct A {
        hi: [i32; 0],
    }
    #[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
        Err(Err(SpannedError {
4
            code: Error::InvalidValueForType {
4
                expected: String::from("an empty array"),
4
                found: String::from("a unit value")
4
            },
4
            span: Span {
4
                start: Position { line: 7, col: 1 },
4
                end: Position { line: 7, col: 2 }
4
            }
4
        }))
    );
4
}
#[test]
4
fn unit_like_zero_length_inside_adjacently_tagged() {
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct TupleStruct();
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct A {
        hi: TupleStruct,
    }
    #[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()
        ),
        Ok(()),
    );
4
    assert_eq!(
4
        ron::from_str::<AdjacentlyTagged>("(tag: B, content: (ho: 24, a: (hi: ())))"),
        Ok(AdjacentlyTagged::B {
            ho: 24,
            a: A { hi: TupleStruct() }
        }),
    );
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
            span: Span {
4
                start: Position { line: 1, col: 40 },
4
                end: Position { line: 1, col: 40 }
4
            }
4
        })
    );
4
}
#[test]
4
fn unit_like_zero_length_inside_untagged() {
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct Struct {}
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct A {
        hi: Struct,
    }
    #[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
        Err(Err(SpannedError {
4
            code: Error::Message(String::from(
4
                "data did not match any variant of untagged enum Untagged"
4
            )),
4
            span: Span {
4
                start: Position { line: 6, col: 1 },
4
                end: Position { line: 6, col: 2 }
4
            }
4
        }))
    );
4
}
#[test]
4
fn unit_like_zero_length_inside_flatten_struct() {
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    enum Enum {
        Tuple(),
    }
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct A {
        hi: Enum,
    }
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct B {
        a: A,
    }
    #[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
        Err(Err(SpannedError {
4
            code: Error::InvalidValueForType {
4
                expected: String::from("tuple variant"),
4
                found: String::from("a unit value")
4
            },
4
            span: Span {
4
                start: Position { line: 6, col: 1 },
4
                end: Position { line: 6, col: 1 }
4
            }
4
        }))
    );
4
}
#[test]
4
fn unit_like_zero_length_inside_flatten_struct_variant() {
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    enum Enum {
        Struct {},
    }
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct A {
        hi: Enum,
    }
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct B {
        a: A,
    }
    #[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
        Err(Err(SpannedError {
4
            code: Error::InvalidValueForType {
4
                expected: String::from("struct variant"),
4
                found: String::from("a unit value")
4
            },
4
            span: Span {
4
                start: Position { line: 6, col: 1 },
4
                end: Position { line: 6, col: 1 }
4
            }
4
        }))
    );
4
}
#[test]
4
fn i128_inside_internally_tagged() {
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct A {
        hi: i128,
    }
    #[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
        Err(Ok(Error::Message(String::from("i128 is not supported"))))
    );
    #[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
        Err(Err(SpannedError {
2
            code: Error::InvalidValueForType {
2
                expected: String::from("any value"),
2
                found: format!("integer `{}` as u128", i128::MAX)
2
            },
2
            span: Span {
2
                start: Position { line: 5, col: 13 },
2
                end: Position { line: 5, col: 52 }
2
            }
2
        }))
    );
4
}
#[test]
4
fn u128_inside_adjacently_tagged() {
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct A {
        hi: u128,
    }
    #[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
        Err(Ok(Error::Message(String::from("u128 is not supported"))))
    );
    #[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()
        ),
        Ok(()),
    );
    #[cfg(feature = "integer128")]
2
    assert_eq!(
2
        ron::from_str::<AdjacentlyTagged>(&format!(
2
            "(tag: B, content: (ho: 24, a: (hi: {})))",
2
            u128::MAX
2
        ),),
        Ok(AdjacentlyTagged::B {
            ho: 24,
            a: A { hi: u128::MAX }
        }),
    );
    #[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
            span: Span {
2
                start: Position { line: 1, col: 28 },
2
                end: 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
        Err(Ok(Error::Message(String::from("i128 is not supported"))))
    );
    #[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
        Err(Err(SpannedError {
2
            code: Error::InvalidValueForType {
2
                expected: String::from("any value"),
2
                found: format!("integer `{}` as i128", i128::MIN)
2
            },
2
            span: Span {
2
                start: Position { line: 4, col: 14 },
2
                end: 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,
    }
    #[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
        Err(Ok(Error::Message(String::from("u128 is not supported"))))
    );
    #[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
        Err(Err(SpannedError {
2
            code: Error::InvalidValueForType {
2
                expected: String::from("any value"),
2
                found: format!("integer `{}` as u128", u128::MAX)
2
            },
2
            span: Span {
2
                start: Position { line: 4, col: 13 },
2
                end: 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,
    }
    #[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
        Err(Ok(Error::Message(String::from("i128 is not supported"))))
    );
    #[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
        Err(Err(SpannedError {
2
            code: Error::InvalidValueForType {
2
                expected: String::from("any value"),
2
                found: format!("integer `{}` as i128", i128::MIN)
2
            },
2
            span: Span {
2
                start: Position { line: 4, col: 14 },
2
                end: Position { line: 4, col: 53 }
2
            }
2
        }))
    );
4
}
#[test]
4
fn duplicate_key_inside_flatten_struct() {
    #[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()
        ),
        Err(Err(SpannedError {
            code: Error::DuplicateStructField {
                field: "ho",
                outer: None
            },
            span: Span {
                start: Position { line: 3, col: 6 },
                end: Position { line: 3, col: 9 }
            }
        }))
    );
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,
    }
    #[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
        Err(Err(SpannedError {
4
            code: Error::DuplicateStructField {
4
                field: "ho",
4
                outer: Some(String::from("A"))
4
            },
4
            span: Span {
4
                start: Position { line: 3, col: 6 },
4
                end: Position { line: 3, col: 9 }
4
            }
4
        }))
    );
4
}
#[test]
4
fn non_string_key_inside_flatten_struct() {
    #[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()
        ),
        Err(Err(SpannedError {
            code: Error::ExpectedString,
            span: Span {
                start: Position { line: 3, col: 5 },
                end: Position { line: 3, col: 5 }
            }
        }))
    );
4
}
#[test]
4
fn non_string_key_inside_flatten_struct_variant() {
    #[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()
        ),
        Err(Err(SpannedError {
            code: Error::ExpectedString,
            span: Span {
                start: Position { line: 3, col: 5 },
                end: Position { line: 3, col: 5 }
            }
        }))
    );
4
}
#[test]
4
fn more_than_one_flatten_map_inside_flatten_struct() {
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct Deep {
        #[serde(flatten)]
        other: HashMap<String, bool>,
    }
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct Inner {
        #[serde(flatten)]
        deep: Deep,
    }
    #[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()
        ),
        // 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
}
#[test]
4
fn more_than_one_flatten_map_inside_flatten_struct_variant() {
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct Deep {
        #[serde(flatten)]
        other: HashMap<String, bool>,
    }
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct Inner {
        #[serde(flatten)]
        deep: Deep,
    }
    #[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()
        ),
        // 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
}
#[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,
    }
    #[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
        Err(Err(SpannedError {
4
            code: Error::InvalidValueForType {
4
                expected: String::from("i32"),
4
                found: String::from("a map")
4
            },
4
            span: Span {
4
                start: Position { line: 6, col: 1 },
4
                end: 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,
    }
    #[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
        Err(Err(SpannedError {
4
            code: Error::InvalidValueForType {
4
                expected: String::from("i32"),
4
                found: String::from("a map")
4
            },
4
            span: Span {
4
                start: Position { line: 6, col: 1 },
4
                end: Position { line: 6, col: 1 }
4
            }
4
        }))
    );
4
}
#[test]
4
fn untagged_flatten_struct_variant_beside_map_inside_flatten_struct() {
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    #[serde(untagged)]
    enum Flattened {
        Struct {
            hi: i32,
            #[serde(flatten)]
            flat: (),
        },
    }
    #[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
        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
}
#[test]
4
fn untagged_flatten_struct_variant_beside_map_inside_flatten_struct_variant() {
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    #[serde(untagged)]
    enum Flattened {
        Struct {
            hi: i32,
            #[serde(flatten)]
            flat: (),
        },
    }
    #[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
        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
}
#[test]
4
fn externally_tagged_newtype_variant_beside_map_inside_flatten_struct_variant() {
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    enum Flattened {
        Newtype(()),
    }
    #[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
        Err(Err(SpannedError {
4
            code: Error::InvalidValueForType {
4
                expected: String::from("i32"),
4
                found: String::from("a unit value")
4
            },
4
            span: Span {
4
                start: Position { line: 4, col: 1 },
4
                end: 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 },
    }
    #[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
        Err(Err(SpannedError {
4
            code: Error::InvalidValueForType {
4
                expected: String::from("i32"),
4
                found: String::from("a map")
4
            },
4
            span: Span {
4
                start: Position { line: 6, col: 1 },
4
                end: 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),
    }
    #[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
        Err(Err(SpannedError {
4
            code: Error::InvalidValueForType {
4
                expected: String::from("i32"),
4
                found: String::from("a sequence")
4
            },
4
            span: Span {
4
                start: Position { line: 7, col: 1 },
4
                end: 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,
    }
    #[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
        Err(Err(SpannedError {
4
            code: Error::InvalidValueForType {
4
                expected: String::from("i32"),
4
                found: String::from("the string \"Unit\"")
4
            },
4
            span: Span {
4
                start: Position { line: 4, col: 1 },
4
                end: 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(()),
    }
    #[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
        Err(Err(SpannedError {
4
            code: Error::InvalidValueForType {
4
                expected: String::from("i32"),
4
                found: String::from("the string \"Newtype\"")
4
            },
4
            span: Span {
4
                start: Position { line: 4, col: 1 },
4
                end: 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 },
    }
    #[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
        Err(Err(SpannedError {
4
            code: Error::InvalidValueForType {
4
                expected: String::from("i32"),
4
                found: String::from("the string \"Struct\"")
4
            },
4
            span: Span {
4
                start: Position { line: 5, col: 1 },
4
                end: 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,
    }
    #[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
        Err(Err(SpannedError {
4
            code: Error::InvalidValueForType {
4
                expected: String::from("i32"),
4
                found: String::from("the string \"Unit\"")
4
            },
4
            span: Span {
4
                start: Position { line: 4, col: 1 },
4
                end: 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(()),
    }
    #[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
        Err(Err(SpannedError {
4
            code: Error::InvalidValueForType {
4
                expected: String::from("i32"),
4
                found: String::from("the string \"Newtype\"")
4
            },
4
            span: Span {
4
                start: Position { line: 5, col: 1 },
4
                end: Position { line: 5, col: 1 }
4
            }
4
        }))
    );
4
}
#[test]
4
fn adjacently_tagged_struct_variant_beside_map_inside_flatten_struct() {
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    #[serde(tag = "tag", content = "content")]
    enum Flattened {
        Struct { hi: i32 },
    }
    #[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
        Err(Err(SpannedError {
4
            code: Error::InvalidValueForType {
4
                expected: String::from("i32"),
4
                found: String::from("the string \"Struct\"")
4
            },
4
            span: Span {
4
                start: Position { line: 7, col: 1 },
4
                end: Position { line: 7, col: 1 }
4
            }
4
        }))
    );
4
}
#[test]
4
fn adjacently_tagged_tuple_variant_beside_map_inside_flatten_struct_variant() {
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    #[serde(tag = "tag", content = "content")]
    enum Flattened {
        Tuple(i32, bool),
    }
    #[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
        Err(Err(SpannedError {
4
            code: Error::InvalidValueForType {
4
                expected: String::from("i32"),
4
                found: String::from("the string \"Tuple\"")
4
            },
4
            span: Span {
4
                start: Position { line: 5, col: 1 },
4
                end: 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,
    }
    #[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
        Err(Err(SpannedError {
4
            code: Error::InvalidValueForType {
4
                expected: String::from("i32"),
4
                found: String::from("the string \"Flattened\"")
4
            },
4
            span: Span {
4
                start: Position { line: 5, col: 1 },
4
                end: 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,
    }
    #[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
        Err(Err(SpannedError {
4
            code: Error::InvalidValueForType {
4
                expected: String::from("i32"),
4
                found: String::from("the string \"Flattened\"")
4
            },
4
            span: Span {
4
                start: Position { line: 5, col: 1 },
4
                end: Position { line: 5, col: 1 }
4
            }
4
        }))
    );
4
}
#[test]
4
fn zero_length_untagged_tuple_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
            span: Span {
4
                start: Position { line: 1, col: 1 },
4
                end: 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
            span: Span {
4
                start: Position { line: 1, col: 1 },
4
                end: 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
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    #[serde(untagged)]
    enum Untagged {
        OneTuple(i32, #[serde(skip)] ()),
    }
4
    assert_eq!(
4
        check_roundtrip(&Untagged::OneTuple(42, ()), PrettyConfig::default()),
        Ok(())
    );
4
    assert_eq!(
4
        check_roundtrip(
4
            &Untagged::OneTuple(42, ()),
4
            PrettyConfig::default().extensions(Extensions::UNWRAP_VARIANT_NEWTYPES)
        ),
        Ok(())
    );
4
}
#[test]
4
fn unit_inside_untagged_newtype_variant_inside_internally_tagged_newtype_variant() {
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    #[serde(untagged)]
    enum Untagged {
        Newtype(()),
    }
    #[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
        Err(Err(SpannedError {
4
            code: Error::Message(String::from(
4
                "data did not match any variant of untagged enum Untagged"
4
            )),
4
            span: Span {
4
                start: Position { line: 3, col: 1 },
4
                end: 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(()),
    }
    #[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
        Err(Err(SpannedError {
4
            code: Error::Message(String::from(
4
                "data did not match any variant of untagged enum Untagged"
4
            )),
4
            span: Span {
4
                start: Position { line: 3, col: 1 },
4
                end: Position { line: 3, col: 1 }
4
            }
4
        }))
    );
4
}
#[test]
4
fn unit_struct_inside_untagged_newtype_variant_inside_internally_tagged_newtype_variant() {
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct Unit;
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    #[serde(untagged)]
    enum Untagged {
        Newtype(Unit),
    }
    #[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
        Err(Err(SpannedError {
4
            code: Error::Message(String::from(
4
                "data did not match any variant of untagged enum Untagged"
4
            )),
4
            span: Span {
4
                start: Position { line: 3, col: 1 },
4
                end: 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,
    }
    #[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
        Err(Err(SpannedError {
4
            code: Error::Message(String::from(
4
                "data did not match any variant of untagged enum Untagged"
4
            )),
4
            span: Span {
4
                start: Position { line: 3, col: 1 },
4
                end: Position { line: 3, col: 1 }
4
            }
4
        }))
    );
4
}
#[test]
4
fn untagged_unit_variant_inside_flatten_struct_variant() {
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    enum Enum {
        Unit,
    }
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    #[serde(untagged)]
    enum Untagged {
        Unit,
        Newtype(Enum),
    }
    #[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()
        ),
        Ok(())
    );
4
    assert_eq!(
4
        check_roundtrip(
4
            &InternallyTagged::Newtype(Untagged::Unit),
4
            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
            span: Span {
4
                start: Position { line: 3, col: 1 },
4
                end: 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,
    }
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    #[serde(tag = "tag")]
    enum InternallyTagged {
        Newtype(()),
    }
    #[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
        Err(Err(SpannedError {
4
            code: Error::InvalidValueForType {
4
                expected: String::from("unit"),
4
                found: String::from("a map")
4
            },
4
            span: Span {
4
                start: Position { line: 5, col: 1 },
4
                end: 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,
    }
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    #[serde(tag = "tag")]
    enum InternallyTagged {
        Newtype(Untagged),
    }
    #[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
        Err(Err(SpannedError {
4
            code: Error::Message(String::from(
4
                "data did not match any variant of untagged enum Untagged"
4
            )),
4
            span: Span {
4
                start: Position { line: 5, col: 1 },
4
                end: 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(()),
    }
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    #[serde(tag = "tag")]
    enum InternallyTagged {
        Newtype(ExternallyTagged),
    }
    #[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
        Err(Err(SpannedError {
4
            code: Error::InvalidValueForType {
4
                expected: String::from("map with a single key"),
4
                found: String::from("a map"),
4
            },
4
            span: Span {
4
                start: Position { line: 5, col: 1 },
4
                end: 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(()),
    }
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    #[serde(tag = "tag")]
    enum InternallyTagged {
        Newtype(ExternallyTagged),
    }
    #[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
        Err(Err(SpannedError {
4
            code: Error::InvalidValueForType {
4
                expected: String::from("map with a single key"),
4
                found: String::from("a map"),
4
            },
4
            span: Span {
4
                start: Position { line: 7, col: 1 },
4
                end: Position { line: 7, col: 1 }
4
            }
4
        }))
    );
4
}
#[test]
4
fn flattened_map_inside_option_beside_flattened_struct_variant() {
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    #[serde(untagged)]
    enum Untagged {
        Struct { a: i32 },
    }
    #[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
        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
}
#[test]
4
fn flattened_untagged_struct_beside_flattened_untagged_struct() {
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    #[serde(untagged)]
    enum Untagged {
        Struct { a: i32 },
        Other { b: i32 },
    }
    #[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
        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
}
#[test]
4
fn flattened_field_inside_flattened_struct_alongside_map() {
    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    struct Units {
        a: i32,
        #[serde(flatten)]
        b: (),
    }
    #[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
        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
}
376
fn check_roundtrip<T: PartialEq + core::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
}