use proc_macro::TokenStream;
use quote::quote;
use syn::{Data, DeriveInput, Fields, parse_macro_input, Path};
#[proc_macro_derive(FromInto)]
pub fn from_into(_input: TokenStream) -> TokenStream {
let ast: DeriveInput = parse_macro_input!(_input as DeriveInput);
let _self = &ast.ident;
let _other = match ast.data {
Data::Struct(ref data) => {
match data.fields {
Fields::Unnamed(ref fields) => {
if fields.unnamed.is_empty() {
panic!("There is no unnamed parameter in struct")
}
if fields.unnamed.iter().count().ne(&1) {
panic!("There are more than one unnamed parameter in struct")
} else {
fields.unnamed.first().unwrap()
}
}
_ => panic!("There is no unnamed parameter in struct")
}
}
_ => panic!("This is not a struct")
};
let gen = quote! {
impl From<#_other> for #_self{
fn from(value: #_other) -> Self{
Self(value)
}
}
impl Into<#_other> for #_self{
fn into(self) -> #_other{
self.0
}
}
};
gen.into()
}
#[proc_macro_attribute]
pub fn self_attr(_attr: TokenStream, item: TokenStream) -> TokenStream
{
let args = _attr.to_string();
let mut func = parse_macro_input!(item as syn::ItemImpl);
let _self = &func.self_ty;
for arg in args.split(",") {
let attr = syn::parse_str::<Path>(arg).expect("4").segments.last().expect("5").clone();
let target_attr = syn::parse_str::<Path>(arg).expect("3");
func.items.push(syn::parse2(quote!(pub const #attr: #_self = #_self(#target_attr);)).expect("2"));
}
quote!( #func ).into()
}
#[allow(non_snake_case)]
#[proc_macro]
pub fn PCWSTR(input: TokenStream) -> TokenStream {
let input_str = input.to_string();
if input_str.starts_with("vec") {
let trim_input = input_str.trim_start_matches("vec").trim(); let output = format!("windows::core::PCWSTR::from_raw(widestring::U16CString::from_vec({}).unwrap().into_raw())", trim_input);
output.parse().unwrap()
} else {
let output = format!("windows::core::PCWSTR::from_raw(widestring::U16CString::from_str({}).unwrap().into_raw())", input_str);
output.parse().unwrap()
}
}
#[allow(non_snake_case)]
#[proc_macro]
pub fn PWSTR(input: TokenStream) -> TokenStream {
let input_str = input.to_string();
if input_str.starts_with("vec") {
let trim_input = input_str.trim_start_matches("vec").trim();
let output = format!("windows::core::PWSTR::from_raw(widestring::U16CString::from_vec({}).unwrap().into_raw())", trim_input);
output.parse().unwrap()
} else {
let output = format!("windows::core::PWSTR::from_raw(widestring::U16CString::from_str({}).unwrap().into_raw())", input_str);
output.parse().unwrap()
}
}