use crate::core_impl::info_extractor::serializer_attr::SerializerAttr;
use crate::core_impl::info_extractor::SerializerType;
use quote::ToTokens;
use syn::{spanned::Spanned, Attribute, Error, Ident, Pat, PatType, Token, Type};
pub enum BindgenArgType {
Regular,
CallbackArg,
CallbackResultArg,
CallbackArgVec,
}
pub struct ArgInfo {
pub non_bindgen_attrs: Vec<Attribute>,
pub ident: Ident,
pub pat_reference: Option<Token![ref]>,
pub pat_mutability: Option<Token![mut]>,
pub reference: Option<Token![&]>,
pub mutability: Option<Token![mut]>,
pub ty: Type,
pub bindgen_ty: BindgenArgType,
pub serializer_ty: SerializerType,
pub original: PatType,
}
impl ArgInfo {
pub fn new(original: &mut PatType) -> syn::Result<Self> {
let mut non_bindgen_attrs = vec![];
let pat_reference;
let pat_mutability;
let ident;
match original.pat.as_ref() {
Pat::Ident(pat_ident) => {
pat_reference = pat_ident.by_ref;
pat_mutability = pat_ident.mutability;
ident = pat_ident.ident.clone();
}
_ => {
return Err(Error::new(
original.span(),
"Only identity patterns are supported in function arguments.",
));
}
};
let (reference, mutability, ty) = match original.ty.as_ref() {
x @ Type::Array(_) | x @ Type::Path(_) | x @ Type::Tuple(_) => {
(None, None, (*x).clone())
}
Type::Reference(r) => (Some(r.and_token), r.mutability, (*r.elem.as_ref()).clone()),
_ => return Err(Error::new(original.span(), "Unsupported argument type.")),
};
let mut bindgen_ty = BindgenArgType::Regular;
let mut serializer_ty = SerializerType::JSON;
for attr in &mut original.attrs {
let attr_str = attr.path.to_token_stream().to_string();
match attr_str.as_str() {
"callback" | "callback_unwrap" => {
bindgen_ty = BindgenArgType::CallbackArg;
}
"callback_result" => {
bindgen_ty = BindgenArgType::CallbackResultArg;
}
"callback_vec" => {
bindgen_ty = BindgenArgType::CallbackArgVec;
}
"serializer" => {
let serializer: SerializerAttr = syn::parse2(attr.tokens.clone())?;
serializer_ty = serializer.serializer_type;
}
_ => {
non_bindgen_attrs.push((*attr).clone());
}
}
}
original.attrs.retain(|attr| {
let attr_str = attr.path.to_token_stream().to_string();
attr_str != "callback"
&& attr_str != "callback_vec"
&& attr_str != "serializer"
&& attr_str != "callback_result"
&& attr_str != "callback_unwrap"
});
Ok(Self {
non_bindgen_attrs,
ident,
pat_reference,
pat_mutability,
reference,
mutability,
ty,
bindgen_ty,
serializer_ty,
original: original.clone(),
})
}
}