use std::env; use syn::{spanned::Spanned, *}; macro_rules! syn_error { ($src:expr, $($fmt:expr),+) => {{ return Err(syn::Error::new($src.span(), format!($($fmt),*))); }}; } macro_rules! syn_assert { ($cond:expr, $src:expr, $($fmt:expr),+) => {{ if !$cond { crate::utils::syn_error!($src, $($fmt),+); } }}; } pub(crate) use {syn_assert, syn_error}; pub fn ffi_crate() -> Path { match ( env::var("CARGO_PKG_NAME").ok(), env::var("CARGO_TARGET_TMPDIR").ok(), // ignore tests/**/*.rs ) { (Some(name), None) if name == "luaffi" => parse_quote!(crate), _ => parse_quote!(::luaffi), } } pub fn ty_name(ty: &Type) -> Result<&Ident> { match ty { Type::Path(path) => path.path.require_ident(), _ => syn_error!(ty, "expected ident"), } } pub fn pat_ident(pat: &Pat) -> Result { Ok(match pat { Pat::Ident(ident) => match ident.subpat { Some((_, ref subpat)) => syn_error!(subpat, "unexpected subpattern"), None => ident.ident.clone(), }, Pat::Wild(wild) => Ident::new("_", wild.span()), _ => syn_error!(pat, "expected ident"), }) } pub fn is_unit(ty: &Type) -> bool { if let Type::Tuple(tuple) = ty && tuple.elems.is_empty() { true } else { false } } pub fn is_primitivelike(ty: &Type) -> bool { match ty { Type::Tuple(tuple) if tuple.elems.is_empty() => true, // unit type Type::Reference(_) | Type::Ptr(_) => true, Type::Paren(paren) => is_primitivelike(&paren.elem), Type::Path(path) => { if let Some(name) = path.path.get_ident() { matches!( format!("{name}").as_str(), "bool" | "u8" | "u16" | "u32" | "u64" | "usize" | "i8" | "i16" | "i32" | "i64" | "isize" | "f32" | "f64" | "char" | "c_char" | "c_schar" | "c_uchar" | "c_short" | "c_ushort" | "c_int" | "c_uint" | "c_long" | "c_ulong" | "c_longlong" | "c_ulonglong" | "c_float" | "c_double" | "c_size_t" | "c_ssize_t" | "c_ptrdiff_t" ) } else { false } } _ => false, } }