1extern crate proc_macro;
2use proc_macro::{TokenStream, TokenTree};
3use proc_macro_hack::proc_macro_hack;
4
5#[proc_macro_hack]
6pub fn wide_str(ts: TokenStream) -> TokenStream {
7 let mut iter = ts.into_iter();
8 if let Some(TokenTree::Literal(lit)) = iter.next() {
9 if iter.next().is_some() {
10 panic!("Invalid argument(s)!");
11 }
12 let old: String = lit.to_string();
13 let mut new: String = String::new();
14 let len = old.len();
15
16 let mut iter = old.chars().skip(1).take(len - 2);
17 while let Some(c) = iter.next() {
18 if c == '\\' {
19 new.push(match iter.next().unwrap() {
20 'n' => '\n',
21 'r' => '\r',
22 't' => '\t',
23 '0' => '\0',
24
25 'x' => {
26 let mut code_iter = (&mut iter).take(2);
27 if (&mut code_iter).count() != 2 {
28 panic!(r"this form of character escape may only be used with characters in the range [\x00-\x7f]");
29 }
30 let parsed = u8::from_str_radix(&code_iter.collect::<String>(), 16).unwrap_or_else(|_| panic!("Syntax Error: ASCII hex escape code must contain only hex characters"));
31 if parsed > b'\x7F' {
32 panic!("Syntax Error: ASCII hex escape code must be at most 0x7F");
33 }
34 parsed as char
35 },
36 'u' => {
37 if iter.next() != Some('{') {
38 panic!("Syntax Error: Missing `{` to begin the unicode escape");
39 }
40 let code_iter = (&mut iter).take_while(|x| *x != '}').filter(|x| *x != '_').enumerate();
41 let parsed = u32::from_str_radix(&code_iter.map(|val| {
42 let (i, c) = val;
43 if i > 6 {
44 panic!("Syntax Error: Unicode escape code must have at most 6 digits");
45 }
46 c
47 }).collect::<String>(), 16).unwrap_or_else(|_| panic!("Syntax Error: ASCII hex escape code must contain only hex characters"));
48 core::char::from_u32(parsed).expect("Syntax Error: Unicode escape code must be at most 0x10FFFF")
49 },
50
51 c => c,
52 });
53 } else {
54 new.push(c);
55 }
56 }
57 new.push('\0');
58
59 let mut result = "[".to_string();
60 for c in new.chars() {
61 result.push_str(&format!("0x{:x}, ", c as u16));
62 }
63 result.push(']');
64
65 result.parse().unwrap()
66 } else {
67 panic!("Invalid argument(s)!");
68 }
69}