wstr_impl 0.2.0

Private macro implementations for compile-time UTF-16 (wide) string literals.
Documentation
#[macro_use]
extern crate proc_macro_hack;
extern crate syn;

use syn::{TokenTree, Token, Lit};

fn input_to_utf16_vec(input: &str) -> Vec<u16> {
    let ast = &syn::parse_token_trees(input).unwrap()[0];
    if let TokenTree::Token(Token::Literal(Lit::Str(ref s, _))) = *ast {
        s.encode_utf16().collect()
    } else {
        panic!("input must be string literal");
    }
}

fn input_to_utf16_nullterm_vec(input: &str) -> Vec<u16> {
    let ast = &syn::parse_token_trees(input).unwrap()[0];
    if let TokenTree::Token(Token::Literal(Lit::Str(ref s, _))) = *ast {
        let mut s = s.to_string();
        s.push('\0');
        s.encode_utf16().collect()
    } else {
        panic!("input must be string literal");
    }
}

fn generate_u16_str_arr_code<F>(input: &str, parser: F) -> String
    where F: FnOnce(&str) -> Vec<u16> {
    let utf16_vec = parser(input);
    format!("{{ static _U16_STR_ARR: [u16; {}] = {:?}; &_U16_STR_ARR }}", utf16_vec.len(), utf16_vec)
}

proc_macro_expr_impl! {
    pub fn wstr_impl(input: &str) -> String {
        generate_u16_str_arr_code(input, &input_to_utf16_vec)
    }

    pub fn wstrz_impl(input: &str) -> String {
        generate_u16_str_arr_code(input, &input_to_utf16_nullterm_vec)
    }
}