]>
Commit | Line | Data |
---|---|---|
e74abb32 XL |
1 | mod features; |
2 | ||
3 | use proc_macro2::{TokenStream, TokenTree}; | |
4 | use quote::ToTokens; | |
5 | use std::str::FromStr; | |
6 | use syn::Lit; | |
7 | ||
8 | fn lit(s: &str) -> Lit { | |
9 | match TokenStream::from_str(s) | |
10 | .unwrap() | |
11 | .into_iter() | |
12 | .next() | |
13 | .unwrap() | |
14 | { | |
15 | TokenTree::Literal(lit) => Lit::new(lit), | |
16 | _ => panic!(), | |
17 | } | |
18 | } | |
19 | ||
20 | #[test] | |
21 | fn strings() { | |
22 | fn test_string(s: &str, value: &str) { | |
23 | match lit(s) { | |
24 | Lit::Str(lit) => { | |
25 | assert_eq!(lit.value(), value); | |
26 | let again = lit.into_token_stream().to_string(); | |
27 | if again != s { | |
28 | test_string(&again, value); | |
29 | } | |
30 | } | |
31 | wrong => panic!("{:?}", wrong), | |
32 | } | |
33 | } | |
34 | ||
35 | test_string("\"a\"", "a"); | |
36 | test_string("\"\\n\"", "\n"); | |
37 | test_string("\"\\r\"", "\r"); | |
38 | test_string("\"\\t\"", "\t"); | |
39 | test_string("\"🐕\"", "🐕"); // NOTE: This is an emoji | |
40 | test_string("\"\\\"\"", "\""); | |
41 | test_string("\"'\"", "'"); | |
42 | test_string("\"\"", ""); | |
43 | test_string("\"\\u{1F415}\"", "\u{1F415}"); | |
44 | test_string( | |
45 | "\"contains\nnewlines\\\nescaped newlines\"", | |
46 | "contains\nnewlinesescaped newlines", | |
47 | ); | |
48 | test_string("r\"raw\nstring\\\nhere\"", "raw\nstring\\\nhere"); | |
49 | } | |
50 | ||
51 | #[test] | |
52 | fn byte_strings() { | |
53 | fn test_byte_string(s: &str, value: &[u8]) { | |
54 | match lit(s) { | |
55 | Lit::ByteStr(lit) => { | |
56 | assert_eq!(lit.value(), value); | |
57 | let again = lit.into_token_stream().to_string(); | |
58 | if again != s { | |
59 | test_byte_string(&again, value); | |
60 | } | |
61 | } | |
62 | wrong => panic!("{:?}", wrong), | |
63 | } | |
64 | } | |
65 | ||
66 | test_byte_string("b\"a\"", b"a"); | |
67 | test_byte_string("b\"\\n\"", b"\n"); | |
68 | test_byte_string("b\"\\r\"", b"\r"); | |
69 | test_byte_string("b\"\\t\"", b"\t"); | |
70 | test_byte_string("b\"\\\"\"", b"\""); | |
71 | test_byte_string("b\"'\"", b"'"); | |
72 | test_byte_string("b\"\"", b""); | |
73 | test_byte_string( | |
74 | "b\"contains\nnewlines\\\nescaped newlines\"", | |
75 | b"contains\nnewlinesescaped newlines", | |
76 | ); | |
77 | test_byte_string("br\"raw\nstring\\\nhere\"", b"raw\nstring\\\nhere"); | |
78 | } | |
79 | ||
80 | #[test] | |
81 | fn bytes() { | |
82 | fn test_byte(s: &str, value: u8) { | |
83 | match lit(s) { | |
84 | Lit::Byte(lit) => { | |
85 | assert_eq!(lit.value(), value); | |
86 | let again = lit.into_token_stream().to_string(); | |
87 | assert_eq!(again, s); | |
88 | } | |
89 | wrong => panic!("{:?}", wrong), | |
90 | } | |
91 | } | |
92 | ||
93 | test_byte("b'a'", b'a'); | |
94 | test_byte("b'\\n'", b'\n'); | |
95 | test_byte("b'\\r'", b'\r'); | |
96 | test_byte("b'\\t'", b'\t'); | |
97 | test_byte("b'\\''", b'\''); | |
98 | test_byte("b'\"'", b'"'); | |
99 | } | |
100 | ||
101 | #[test] | |
102 | fn chars() { | |
103 | fn test_char(s: &str, value: char) { | |
104 | match lit(s) { | |
105 | Lit::Char(lit) => { | |
106 | assert_eq!(lit.value(), value); | |
107 | let again = lit.into_token_stream().to_string(); | |
108 | if again != s { | |
109 | test_char(&again, value); | |
110 | } | |
111 | } | |
112 | wrong => panic!("{:?}", wrong), | |
113 | } | |
114 | } | |
115 | ||
116 | test_char("'a'", 'a'); | |
117 | test_char("'\\n'", '\n'); | |
118 | test_char("'\\r'", '\r'); | |
119 | test_char("'\\t'", '\t'); | |
120 | test_char("'🐕'", '🐕'); // NOTE: This is an emoji | |
121 | test_char("'\\''", '\''); | |
122 | test_char("'\"'", '"'); | |
123 | test_char("'\\u{1F415}'", '\u{1F415}'); | |
124 | } | |
125 | ||
126 | #[test] | |
127 | fn ints() { | |
128 | fn test_int(s: &str, value: u64, suffix: &str) { | |
129 | match lit(s) { | |
130 | Lit::Int(lit) => { | |
131 | assert_eq!(lit.base10_digits().parse::<u64>().unwrap(), value); | |
132 | assert_eq!(lit.suffix(), suffix); | |
133 | let again = lit.into_token_stream().to_string(); | |
134 | if again != s { | |
135 | test_int(&again, value, suffix); | |
136 | } | |
137 | } | |
138 | wrong => panic!("{:?}", wrong), | |
139 | } | |
140 | } | |
141 | ||
142 | test_int("5", 5, ""); | |
143 | test_int("5u32", 5, "u32"); | |
144 | test_int("5_0", 50, ""); | |
145 | test_int("5_____0_____", 50, ""); | |
146 | test_int("0x7f", 127, ""); | |
147 | test_int("0x7F", 127, ""); | |
148 | test_int("0b1001", 9, ""); | |
149 | test_int("0o73", 59, ""); | |
150 | test_int("0x7Fu8", 127, "u8"); | |
151 | test_int("0b1001i8", 9, "i8"); | |
152 | test_int("0o73u32", 59, "u32"); | |
153 | test_int("0x__7___f_", 127, ""); | |
154 | test_int("0x__7___F_", 127, ""); | |
155 | test_int("0b_1_0__01", 9, ""); | |
156 | test_int("0o_7__3", 59, ""); | |
157 | test_int("0x_7F__u8", 127, "u8"); | |
158 | test_int("0b__10__0_1i8", 9, "i8"); | |
159 | test_int("0o__7__________________3u32", 59, "u32"); | |
160 | } | |
161 | ||
162 | #[test] | |
163 | fn floats() { | |
164 | #[cfg_attr(feature = "cargo-clippy", allow(float_cmp))] | |
165 | fn test_float(s: &str, value: f64, suffix: &str) { | |
166 | match lit(s) { | |
167 | Lit::Float(lit) => { | |
168 | assert_eq!(lit.base10_digits().parse::<f64>().unwrap(), value); | |
169 | assert_eq!(lit.suffix(), suffix); | |
170 | let again = lit.into_token_stream().to_string(); | |
171 | if again != s { | |
172 | test_float(&again, value, suffix); | |
173 | } | |
174 | } | |
175 | wrong => panic!("{:?}", wrong), | |
176 | } | |
177 | } | |
178 | ||
179 | test_float("5.5", 5.5, ""); | |
180 | test_float("5.5E12", 5.5e12, ""); | |
181 | test_float("5.5e12", 5.5e12, ""); | |
182 | test_float("1.0__3e-12", 1.03e-12, ""); | |
183 | test_float("1.03e+12", 1.03e12, ""); | |
184 | } |