1
use std::collections::HashMap;
2

            
3
use ron::from_str;
4
use serde::Deserialize;
5

            
6
#[derive(Deserialize)]
7
#[allow(dead_code)]
8
struct Newtype(i32);
9

            
10
#[derive(Deserialize)]
11
#[allow(dead_code)]
12
struct Tuple(i32, i32);
13

            
14
#[derive(Deserialize)]
15
#[allow(dead_code)]
16
struct Struct {
17
    a: i32,
18
    b: i32,
19
}
20

            
21
#[derive(Deserialize)]
22
#[allow(dead_code)]
23
enum Enum {
24
    Newtype(i32),
25
    Tuple(i32, i32),
26
    Struct { a: i32, b: i32 },
27
}
28

            
29
#[test]
30
4
fn test_trailing_comma_some() {
31
4
    assert!(from_str::<Option<i32>>("Some(1)").is_ok());
32
4
    assert!(from_str::<Option<i32>>("Some(1,)").is_ok());
33
4
    assert!(from_str::<Option<i32>>("Some(1,,)").is_err());
34
4
}
35

            
36
#[test]
37
4
fn test_trailing_comma_tuple() {
38
4
    assert!(from_str::<(i32, i32)>("(1,2)").is_ok());
39
4
    assert!(from_str::<(i32, i32)>("(1,2,)").is_ok());
40
4
    assert!(from_str::<(i32, i32)>("(1,2,,)").is_err());
41
4
}
42

            
43
#[test]
44
4
fn test_trailing_comma_list() {
45
4
    assert!(from_str::<Vec<i32>>("[1,2]").is_ok());
46
4
    assert!(from_str::<Vec<i32>>("[1,2,]").is_ok());
47
4
    assert!(from_str::<Vec<i32>>("[1,2,,]").is_err());
48
4
}
49

            
50
#[test]
51
4
fn test_trailing_comma_map() {
52
4
    assert!(from_str::<HashMap<i32, bool>>("{1:false,2:true}").is_ok());
53
4
    assert!(from_str::<HashMap<i32, bool>>("{1:false,2:true,}").is_ok());
54
4
    assert!(from_str::<HashMap<i32, bool>>("{1:false,2:true,,}").is_err());
55
4
}
56

            
57
#[test]
58
4
fn test_trailing_comma_newtype_struct() {
59
4
    assert!(from_str::<Newtype>("(1)").is_ok());
60
4
    assert!(from_str::<Newtype>("(1,)").is_ok());
61
4
    assert!(from_str::<Newtype>("(1,,)").is_err());
62
4
}
63

            
64
#[test]
65
4
fn test_trailing_comma_tuple_struct() {
66
4
    assert!(from_str::<Tuple>("(1,2)").is_ok());
67
4
    assert!(from_str::<Tuple>("(1,2,)").is_ok());
68
4
    assert!(from_str::<Tuple>("(1,2,,)").is_err());
69
4
}
70

            
71
#[test]
72
4
fn test_trailing_comma_struct() {
73
4
    assert!(from_str::<Struct>("(a:1,b:2)").is_ok());
74
4
    assert!(from_str::<Struct>("(a:1,b:2,)").is_ok());
75
4
    assert!(from_str::<Struct>("(a:1,b:2,,)").is_err());
76
4
}
77

            
78
#[test]
79
4
fn test_trailing_comma_enum_newtype_variant() {
80
4
    assert!(from_str::<Enum>("Newtype(1)").is_ok());
81
4
    assert!(from_str::<Enum>("Newtype(1,)").is_ok());
82
4
    assert!(from_str::<Enum>("Newtype(1,,)").is_err());
83
4
}
84

            
85
#[test]
86
4
fn test_trailing_comma_enum_tuple_variant() {
87
4
    assert!(from_str::<Enum>("Tuple(1,2)").is_ok());
88
4
    assert!(from_str::<Enum>("Tuple(1,2,)").is_ok());
89
4
    assert!(from_str::<Enum>("Tuple(1,2,,)").is_err());
90
4
}
91

            
92
#[test]
93
4
fn test_trailing_comma_enum_struct_variant() {
94
4
    assert!(from_str::<Enum>("Struct(a:1,b:2)").is_ok());
95
4
    assert!(from_str::<Enum>("Struct(a:1,b:2,)").is_ok());
96
4
    assert!(from_str::<Enum>("Struct(a:1,b:2,,)").is_err());
97
4
}
98

            
99
#[test]
100
4
fn test_trailing_comma_untagged_newtype_variant() {
101
    #[derive(Debug, PartialEq, Deserialize)]
102
    enum Inner {
103
        Newtype(i32),
104
    }
105

            
106
    #[derive(Debug, PartialEq, Deserialize)]
107
    #[serde(untagged)]
108
    enum Untagged {
109
        Enum(Inner),
110
    }
111

            
112
    #[derive(Debug, PartialEq, Deserialize)]
113
    #[serde(untagged)]
114
    enum Element {
115
        Int(i32),
116
        Tuple((Untagged,)),
117
    }
118

            
119
4
    assert_eq!(
120
4
        from_str::<Untagged>("Newtype(1)").unwrap(),
121
        Untagged::Enum(Inner::Newtype(1))
122
    );
123
4
    assert_eq!(
124
4
        from_str::<Untagged>("Newtype(1,)").unwrap(),
125
        Untagged::Enum(Inner::Newtype(1))
126
    );
127
4
    assert_eq!(
128
4
        from_str::<Untagged>("Newtype( 1 , )").unwrap(),
129
        Untagged::Enum(Inner::Newtype(1))
130
    );
131
4
    assert!(from_str::<Untagged>("Newtype(1,,)").is_err());
132

            
133
    // The `)` of the newtype variant must not be skipped and then taken from
134
    // the enclosing tuple, which would accept unbalanced parentheses
135
4
    assert!(from_str::<Vec<Element>>("[(Newtype(1,), 2]").is_err());
136
4
    assert_eq!(
137
4
        from_str::<Vec<Element>>("[(Newtype(1,),), 2]").unwrap(),
138
4
        vec![
139
4
            Element::Tuple((Untagged::Enum(Inner::Newtype(1)),)),
140
4
            Element::Int(2)
141
        ]
142
    );
143
4
}