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