use proc_macro2::TokenStream;
use quote::quote;
use syn::Ident;
use syn::token::Mut;
use crate::derive_getter::{FieldMode, GetterField};
pub enum ContextArg {
SelfArg,
Ident(TokenStream),
}
pub fn derive_getter_method(
context_arg: &ContextArg,
spec: &GetterField,
phantom_generics: Option<TokenStream>,
provider_ident: Option<Ident>,
) -> TokenStream {
let field_name = &spec.field_name;
let phantom_arg = match &spec.phantom_arg_type {
Some(phantom) => {
quote! {
, _phantom: PhantomData< #phantom >
}
}
None => TokenStream::new(),
};
let context_fn_arg = match &context_arg {
ContextArg::SelfArg => {
if spec.receiver_mut.is_none() {
quote! { &self }
} else {
quote! { &mut self }
}
}
ContextArg::Ident(context_type) => {
if spec.receiver_mut.is_none() {
quote! { context: & #context_type}
} else {
quote! { context: &mut #context_type }
}
}
};
let get_field_method = if spec.receiver_mut.is_none() {
quote! { get_field }
} else {
quote! { get_field_mut }
};
let context_var = match &context_arg {
ContextArg::SelfArg => {
quote! { self }
}
ContextArg::Ident(_) => {
quote! { context }
}
};
let call_expr = match provider_ident {
Some(provider_ident) => {
quote! {
#provider_ident :: #get_field_method ( #context_var, ::core::marker::PhantomData #phantom_generics )
}
}
None => {
quote! {
#context_var . #get_field_method ( ::core::marker::PhantomData #phantom_generics )
}
}
};
let call_expr = extend_call_expr(call_expr, &spec.field_mode, &spec.receiver_mut);
let return_type = &spec.return_type;
quote! {
fn #field_name( #context_fn_arg #phantom_arg ) -> #return_type {
#call_expr
}
}
}
pub fn extend_call_expr(
call_expr: TokenStream,
field_mode: &FieldMode,
field_mut: &Option<Mut>,
) -> TokenStream {
match field_mode {
FieldMode::Reference => call_expr,
FieldMode::OptionRef => {
if field_mut.is_none() {
quote! {
#call_expr .as_ref()
}
} else {
quote! {
#call_expr .as_mut()
}
}
}
FieldMode::MRef => {
quote! {
MRef::Ref( #call_expr )
}
}
FieldMode::Str => {
if field_mut.is_none() {
quote! {
#call_expr .as_str()
}
} else {
quote! {
#call_expr .as_mut_str()
}
}
}
FieldMode::Copy => {
quote! {
#call_expr .clone()
}
}
FieldMode::Slice => {
quote! {
#call_expr .as_ref()
}
}
}
}