blob: 53a7ee0c9e1e943752e8202f2bd44ee9e069a5e3 [file] [log] [blame]
David Tolnay360efd22018-01-04 23:35:26 -08001extern crate proc_macro2;
David Tolnay61037c62018-01-05 16:21:03 -08002extern crate quote;
3extern crate syn;
David Tolnay360efd22018-01-04 23:35:26 -08004
David Tolnay61037c62018-01-05 16:21:03 -08005use syn::{FloatSuffix, IntSuffix, Lit};
David Tolnay360efd22018-01-04 23:35:26 -08006use quote::ToTokens;
David Tolnay61037c62018-01-05 16:21:03 -08007use proc_macro2::{Span, TokenNode, TokenStream};
David Tolnay360efd22018-01-04 23:35:26 -08008use std::str::FromStr;
9
10fn lit(s: &str) -> Lit {
David Tolnay61037c62018-01-05 16:21:03 -080011 match TokenStream::from_str(s)
12 .unwrap()
13 .into_iter()
14 .next()
15 .unwrap()
16 .kind
17 {
David Tolnay360efd22018-01-04 23:35:26 -080018 TokenNode::Literal(lit) => Lit::new(lit, Span::default()),
19 _ => panic!(),
20 }
21}
22
23#[test]
24fn strings() {
25 fn test_string(s: &str, value: &str) {
26 match lit(s) {
27 Lit::Str(lit) => {
28 assert_eq!(lit.value(), value);
29 let again = lit.into_tokens().to_string();
30 if again != s {
31 test_string(&again, value);
32 }
33 }
34 wrong => panic!("{:?}", wrong),
35 }
36 }
37
38 test_string("\"a\"", "a");
39 test_string("\"\\n\"", "\n");
40 test_string("\"\\r\"", "\r");
41 test_string("\"\\t\"", "\t");
42 test_string("\"🐕\"", "🐕"); // NOTE: This is an emoji
43 test_string("\"\\\"\"", "\"");
44 test_string("\"'\"", "'");
45 test_string("\"\"", "");
46 test_string("\"\\u{1F415}\"", "\u{1F415}");
David Tolnay61037c62018-01-05 16:21:03 -080047 test_string(
48 "\"contains\nnewlines\\\nescaped newlines\"",
49 "contains\nnewlinesescaped newlines",
50 );
David Tolnay360efd22018-01-04 23:35:26 -080051 test_string("r\"raw\nstring\\\nhere\"", "raw\nstring\\\nhere");
52}
53
54#[test]
55fn byte_strings() {
56 fn test_byte_string(s: &str, value: &[u8]) {
57 match lit(s) {
58 Lit::ByteStr(lit) => {
59 assert_eq!(lit.value(), value);
60 let again = lit.into_tokens().to_string();
61 if again != s {
62 test_byte_string(&again, value);
63 }
64 }
65 wrong => panic!("{:?}", wrong),
66 }
67 }
68
69 test_byte_string("b\"a\"", b"a");
70 test_byte_string("b\"\\n\"", b"\n");
71 test_byte_string("b\"\\r\"", b"\r");
72 test_byte_string("b\"\\t\"", b"\t");
73 test_byte_string("b\"\\\"\"", b"\"");
74 test_byte_string("b\"'\"", b"'");
75 test_byte_string("b\"\"", b"");
David Tolnay61037c62018-01-05 16:21:03 -080076 test_byte_string(
77 "b\"contains\nnewlines\\\nescaped newlines\"",
78 b"contains\nnewlinesescaped newlines",
79 );
David Tolnay360efd22018-01-04 23:35:26 -080080 test_byte_string("br\"raw\nstring\\\nhere\"", b"raw\nstring\\\nhere");
81}
82
83#[test]
84fn bytes() {
85 fn test_byte(s: &str, value: u8) {
86 match lit(s) {
87 Lit::Byte(lit) => {
88 assert_eq!(lit.value(), value);
89 let again = lit.into_tokens().to_string();
90 assert_eq!(again, s);
91 }
92 wrong => panic!("{:?}", wrong),
93 }
94 }
95
96 test_byte("b'a'", b'a');
97 test_byte("b'\\n'", b'\n');
98 test_byte("b'\\r'", b'\r');
99 test_byte("b'\\t'", b'\t');
100 test_byte("b'\\''", b'\'');
101 test_byte("b'\"'", b'"');
102}
103
104#[test]
105fn chars() {
106 fn test_char(s: &str, value: char) {
107 match lit(s) {
108 Lit::Char(lit) => {
109 assert_eq!(lit.value(), value);
110 let again = lit.into_tokens().to_string();
111 if again != s {
112 test_char(&again, value);
113 }
114 }
115 wrong => panic!("{:?}", wrong),
116 }
117 }
118
119 test_char("'a'", 'a');
120 test_char("'\\n'", '\n');
121 test_char("'\\r'", '\r');
122 test_char("'\\t'", '\t');
123 test_char("'🐕'", '🐕'); // NOTE: This is an emoji
124 test_char("'\\''", '\'');
125 test_char("'\"'", '"');
126 test_char("'\\u{1F415}'", '\u{1F415}');
127}
128
129#[test]
130fn ints() {
131 fn test_int(s: &str, value: u64, suffix: IntSuffix) {
132 match lit(s) {
133 Lit::Int(lit) => {
134 assert_eq!(lit.value(), value);
135 assert_eq!(lit.suffix(), suffix);
136 let again = lit.into_tokens().to_string();
137 if again != s {
138 test_int(&again, value, suffix);
139 }
140 }
141 wrong => panic!("{:?}", wrong),
142 }
143 }
144
145 use syn::IntSuffix::*;
146 test_int("5", 5, None);
147 test_int("5u32", 5, U32);
148 test_int("5_0", 50, None);
149 test_int("5_____0_____", 50, None);
150 test_int("0x7f", 127, None);
151 test_int("0x7F", 127, None);
152 test_int("0b1001", 9, None);
153 test_int("0o73", 59, None);
154 test_int("0x7Fu8", 127, U8);
155 test_int("0b1001i8", 9, I8);
156 test_int("0o73u32", 59, U32);
157 test_int("0x__7___f_", 127, None);
158 test_int("0x__7___F_", 127, None);
159 test_int("0b_1_0__01", 9, None);
160 test_int("0o_7__3", 59, None);
161 test_int("0x_7F__u8", 127, U8);
162 test_int("0b__10__0_1i8", 9, I8);
163 test_int("0o__7__________________3u32", 59, U32);
164}
165
166#[test]
167fn floats() {
168 fn test_float(s: &str, value: f64, suffix: FloatSuffix) {
169 match lit(s) {
170 Lit::Float(lit) => {
171 assert_eq!(lit.value(), value);
172 assert_eq!(lit.suffix(), suffix);
173 let again = lit.into_tokens().to_string();
174 if again != s {
175 test_float(&again, value, suffix);
176 }
177 }
178 wrong => panic!("{:?}", wrong),
179 }
180 }
181
182 use syn::FloatSuffix::*;
183 test_float("5.5", 5.5, None);
184 test_float("5.5E12", 5.5e12, None);
185 test_float("5.5e12", 5.5e12, None);
186 test_float("1.0__3e-12", 1.03e-12, None);
187 test_float("1.03e+12", 1.03e12, None);
188}