use proc_macro2::TokenStream as Tokens;
use quote::quote;
use syn::{Ident, Type};
use crate::attrs::attrs;
use crate::case::field_key;
use crate::codegen::Codegen;
use crate::docs::docs;
use crate::marker::{Fallback, Marker};
pub(crate) struct NamedField {
pub(crate) ident: Ident,
pub(crate) ty: Type,
pub(crate) key: String,
pub(crate) doc: String,
pub(crate) default: Option<Fallback>,
pub(crate) skip: bool,
pub(crate) with: Type,
pub(crate) codec: bool,
pub(crate) range: Option<(f64, f64)>,
}
impl NamedField {
pub(crate) fn binding(&self) -> Tokens {
let ident = &self.ident;
if self.skip {
quote! { #ident: _ }
} else {
quote! { #ident }
}
}
}
pub(crate) fn named_fields(
cg: &Codegen,
fields: &syn::FieldsNamed,
) -> syn::Result<Vec<NamedField>> {
let krate = &cg.krate;
fields
.named
.iter()
.map(|f| {
let a = attrs(&f.attrs)?;
let Some(ident) = f.ident.clone() else {
return Err(syn::Error::new_spanned(
f,
"Schema: a named field without a name",
));
};
let skip = a.has(Marker::Skip);
let key = a.rename.unwrap_or_else(|| field_key(&ident, cg.case));
Ok(NamedField {
ident,
ty: f.ty.clone(),
key,
doc: docs(&f.attrs),
skip,
default: a.default,
codec: a.with.is_some(),
with: a
.with
.unwrap_or_else(|| syn::parse_quote!(#krate::with::Plain)),
range: a.range,
})
})
.collect()
}