blob: 2cdc7dc7200053f1d9bff2f4bee70cfee449aecb [file] [log] [blame]
David Tolnay55535012018-01-05 16:39:23 -08001// Copyright 2018 Syn Developers
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
David Tolnay360efd22018-01-04 23:35:26 -08009extern crate proc_macro2;
David Tolnay61037c62018-01-05 16:21:03 -080010extern crate quote;
11extern crate syn;
David Tolnay360efd22018-01-04 23:35:26 -080012
David Tolnayc3f98562018-11-02 08:55:05 -070013mod features;
14
David Tolnayeb7d79b2018-03-31 22:52:17 +020015use proc_macro2::{TokenStream, TokenTree};
David Tolnay360efd22018-01-04 23:35:26 -080016use quote::ToTokens;
David Tolnay360efd22018-01-04 23:35:26 -080017use std::str::FromStr;
David Tolnayeb7d79b2018-03-31 22:52:17 +020018use syn::{FloatSuffix, IntSuffix, Lit};
David Tolnay360efd22018-01-04 23:35:26 -080019
20fn lit(s: &str) -> Lit {
David Tolnay61037c62018-01-05 16:21:03 -080021 match TokenStream::from_str(s)
22 .unwrap()
23 .into_iter()
24 .next()
25 .unwrap()
David Tolnay61037c62018-01-05 16:21:03 -080026 {
Alex Crichton9a4dca22018-03-28 06:32:19 -070027 TokenTree::Literal(lit) => Lit::new(lit),
David Tolnay360efd22018-01-04 23:35:26 -080028 _ => panic!(),
29 }
30}
31
32#[test]
33fn strings() {
34 fn test_string(s: &str, value: &str) {
35 match lit(s) {
36 Lit::Str(lit) => {
37 assert_eq!(lit.value(), value);
Alex Crichtoneaa6e432018-05-17 11:08:58 -070038 let again = lit.into_token_stream().to_string();
David Tolnay360efd22018-01-04 23:35:26 -080039 if again != s {
40 test_string(&again, value);
41 }
42 }
43 wrong => panic!("{:?}", wrong),
44 }
45 }
46
47 test_string("\"a\"", "a");
48 test_string("\"\\n\"", "\n");
49 test_string("\"\\r\"", "\r");
50 test_string("\"\\t\"", "\t");
51 test_string("\"🐕\"", "🐕"); // NOTE: This is an emoji
52 test_string("\"\\\"\"", "\"");
53 test_string("\"'\"", "'");
54 test_string("\"\"", "");
55 test_string("\"\\u{1F415}\"", "\u{1F415}");
David Tolnay61037c62018-01-05 16:21:03 -080056 test_string(
57 "\"contains\nnewlines\\\nescaped newlines\"",
58 "contains\nnewlinesescaped newlines",
59 );
David Tolnay360efd22018-01-04 23:35:26 -080060 test_string("r\"raw\nstring\\\nhere\"", "raw\nstring\\\nhere");
61}
62
63#[test]
64fn byte_strings() {
65 fn test_byte_string(s: &str, value: &[u8]) {
66 match lit(s) {
67 Lit::ByteStr(lit) => {
68 assert_eq!(lit.value(), value);
Alex Crichtoneaa6e432018-05-17 11:08:58 -070069 let again = lit.into_token_stream().to_string();
David Tolnay360efd22018-01-04 23:35:26 -080070 if again != s {
71 test_byte_string(&again, value);
72 }
73 }
74 wrong => panic!("{:?}", wrong),
75 }
76 }
77
78 test_byte_string("b\"a\"", b"a");
79 test_byte_string("b\"\\n\"", b"\n");
80 test_byte_string("b\"\\r\"", b"\r");
81 test_byte_string("b\"\\t\"", b"\t");
82 test_byte_string("b\"\\\"\"", b"\"");
83 test_byte_string("b\"'\"", b"'");
84 test_byte_string("b\"\"", b"");
David Tolnay61037c62018-01-05 16:21:03 -080085 test_byte_string(
86 "b\"contains\nnewlines\\\nescaped newlines\"",
87 b"contains\nnewlinesescaped newlines",
88 );
David Tolnay360efd22018-01-04 23:35:26 -080089 test_byte_string("br\"raw\nstring\\\nhere\"", b"raw\nstring\\\nhere");
90}
91
92#[test]
93fn bytes() {
94 fn test_byte(s: &str, value: u8) {
95 match lit(s) {
96 Lit::Byte(lit) => {
97 assert_eq!(lit.value(), value);
Alex Crichtoneaa6e432018-05-17 11:08:58 -070098 let again = lit.into_token_stream().to_string();
David Tolnay360efd22018-01-04 23:35:26 -080099 assert_eq!(again, s);
100 }
101 wrong => panic!("{:?}", wrong),
102 }
103 }
104
105 test_byte("b'a'", b'a');
106 test_byte("b'\\n'", b'\n');
107 test_byte("b'\\r'", b'\r');
108 test_byte("b'\\t'", b'\t');
109 test_byte("b'\\''", b'\'');
110 test_byte("b'\"'", b'"');
111}
112
113#[test]
114fn chars() {
115 fn test_char(s: &str, value: char) {
116 match lit(s) {
117 Lit::Char(lit) => {
118 assert_eq!(lit.value(), value);
Alex Crichtoneaa6e432018-05-17 11:08:58 -0700119 let again = lit.into_token_stream().to_string();
David Tolnay360efd22018-01-04 23:35:26 -0800120 if again != s {
121 test_char(&again, value);
122 }
123 }
124 wrong => panic!("{:?}", wrong),
125 }
126 }
127
128 test_char("'a'", 'a');
129 test_char("'\\n'", '\n');
130 test_char("'\\r'", '\r');
131 test_char("'\\t'", '\t');
132 test_char("'🐕'", '🐕'); // NOTE: This is an emoji
133 test_char("'\\''", '\'');
134 test_char("'\"'", '"');
135 test_char("'\\u{1F415}'", '\u{1F415}');
136}
137
138#[test]
139fn ints() {
140 fn test_int(s: &str, value: u64, suffix: IntSuffix) {
141 match lit(s) {
142 Lit::Int(lit) => {
143 assert_eq!(lit.value(), value);
144 assert_eq!(lit.suffix(), suffix);
Alex Crichtoneaa6e432018-05-17 11:08:58 -0700145 let again = lit.into_token_stream().to_string();
David Tolnay360efd22018-01-04 23:35:26 -0800146 if again != s {
147 test_int(&again, value, suffix);
148 }
149 }
150 wrong => panic!("{:?}", wrong),
151 }
152 }
153
154 use syn::IntSuffix::*;
155 test_int("5", 5, None);
156 test_int("5u32", 5, U32);
157 test_int("5_0", 50, None);
158 test_int("5_____0_____", 50, None);
159 test_int("0x7f", 127, None);
160 test_int("0x7F", 127, None);
161 test_int("0b1001", 9, None);
162 test_int("0o73", 59, None);
163 test_int("0x7Fu8", 127, U8);
164 test_int("0b1001i8", 9, I8);
165 test_int("0o73u32", 59, U32);
166 test_int("0x__7___f_", 127, None);
167 test_int("0x__7___F_", 127, None);
168 test_int("0b_1_0__01", 9, None);
169 test_int("0o_7__3", 59, None);
170 test_int("0x_7F__u8", 127, U8);
171 test_int("0b__10__0_1i8", 9, I8);
172 test_int("0o__7__________________3u32", 59, U32);
173}
174
175#[test]
176fn floats() {
David Tolnay76ebcdd2018-01-05 17:07:26 -0800177 #[cfg_attr(feature = "cargo-clippy", allow(float_cmp))]
David Tolnay360efd22018-01-04 23:35:26 -0800178 fn test_float(s: &str, value: f64, suffix: FloatSuffix) {
179 match lit(s) {
180 Lit::Float(lit) => {
181 assert_eq!(lit.value(), value);
182 assert_eq!(lit.suffix(), suffix);
Alex Crichtoneaa6e432018-05-17 11:08:58 -0700183 let again = lit.into_token_stream().to_string();
David Tolnay360efd22018-01-04 23:35:26 -0800184 if again != s {
185 test_float(&again, value, suffix);
186 }
187 }
188 wrong => panic!("{:?}", wrong),
189 }
190 }
191
192 use syn::FloatSuffix::*;
193 test_float("5.5", 5.5, None);
194 test_float("5.5E12", 5.5e12, None);
195 test_float("5.5e12", 5.5e12, None);
196 test_float("1.0__3e-12", 1.03e-12, None);
197 test_float("1.03e+12", 1.03e12, None);
198}