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