use crate::prelude::*;
pub(crate) struct FieldWalkBinding {
ident: Ident,
name: String,
}
impl FieldWalkBinding {
#[must_use]
pub fn from_field(field: &Field) -> Self {
Self {
ident: field.name.clone(),
name: field.name.to_string(),
}
}
#[must_use]
pub fn member_ref_from(&self, receiver: TokenStream) -> TokenStream {
let ident = &self.ident;
quote!(&#receiver.#ident)
}
#[must_use]
pub fn member_mut_from(&self, receiver: TokenStream) -> TokenStream {
let ident = &self.ident;
quote!(&mut #receiver.#ident)
}
#[must_use]
pub fn path_segment(&self, paths: &CratePaths) -> TokenStream {
let model = &paths.model;
let name = &self.name;
quote!(#model::visitor::PathSegment::Field(#name))
}
#[must_use]
pub fn field_name(&self) -> &str {
&self.name
}
#[must_use]
pub fn visit_fn_ident(&self) -> Ident {
format_ident!("__visit_field_{}", self.ident)
}
#[must_use]
pub fn visit_mut_fn_ident(&self) -> Ident {
format_ident!("__visit_field_{}_mut", self.ident)
}
#[must_use]
pub fn normalize_fn_ident(&self) -> Ident {
format_ident!("__normalize_field_{}", self.ident)
}
#[must_use]
pub fn validate_fn_ident(&self) -> Ident {
format_ident!("__validate_field_{}", self.ident)
}
}
#[must_use]
pub(crate) fn field_walk_bindings(fields: &FieldList) -> Vec<FieldWalkBinding> {
fields.iter().map(FieldWalkBinding::from_field).collect()
}
pub(crate) fn cardinality_wrapper(
card: Cardinality,
rules: Vec<TokenStream>,
var_expr: TokenStream,
) -> Option<TokenStream> {
if rules.is_empty() {
return None;
}
let body = quote! { #(#rules)* };
let tokens = match card {
Cardinality::One => quote! {
let v = #var_expr;
#body
},
Cardinality::Opt => quote! {
if let ::core::option::Option::Some(v) = #var_expr {
#body
}
},
Cardinality::Many => {
let item = format_ident!("__item");
quote! {
for #item in #var_expr {
let v = #item;
#body
}
}
}
};
Some(tokens)
}