use crate::UsedType;
use proc_macro2::{Span, TokenStream as TokenStream2};
use quote::{quote, ToTokens, TokenStreamExt};
use syn::{FnArg, Pat};
#[derive(Debug, Clone)]
pub struct PgExternArgument {
pub fn_arg: syn::FnArg,
pub pat: syn::Ident,
pub used_ty: UsedType,
}
impl PgExternArgument {
pub fn build(fn_arg: FnArg) -> Result<Self, syn::Error> {
match &fn_arg {
syn::FnArg::Typed(pat) => Self::build_from_pat_type(fn_arg.clone(), pat.clone()),
syn::FnArg::Receiver(_) => {
Err(syn::Error::new(Span::call_site(), "Unable to parse FnArg that is Self"))
}
}
}
pub fn build_from_pat_type(
fn_arg: syn::FnArg,
value: syn::PatType,
) -> Result<Self, syn::Error> {
let identifier = match *value.pat {
Pat::Ident(ref p) => p.ident.clone(),
Pat::Reference(ref p_ref) => match *p_ref.pat {
Pat::Ident(ref inner_ident) => inner_ident.ident.clone(),
_ => return Err(syn::Error::new(Span::call_site(), "Unable to parse FnArg")),
},
_ => return Err(syn::Error::new(Span::call_site(), "Unable to parse FnArg")),
};
let used_ty = UsedType::new(*value.ty)?;
Ok(PgExternArgument { fn_arg, pat: identifier, used_ty })
}
pub fn entity_tokens(&self) -> TokenStream2 {
let pat = &self.pat;
let used_ty_entity = self.used_ty.entity_tokens();
let quoted = quote! {
::pgrx::pgrx_sql_entity_graph::PgExternArgumentEntity {
pattern: stringify!(#pat),
used_ty: #used_ty_entity,
}
};
quoted
}
}
impl ToTokens for PgExternArgument {
fn to_tokens(&self, tokens: &mut TokenStream2) {
let fn_arg = &self.fn_arg;
let quoted = quote! {
#fn_arg
};
tokens.append_all(quoted);
}
}