wide_str_impl/
lib.rs

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}