This commit is contained in:
Antonio Scandurra 2023-10-13 19:05:51 +02:00
parent 90f226193c
commit fedb787b4f
5 changed files with 239 additions and 29 deletions

View file

@ -79,7 +79,11 @@ pub fn derive_refineable(input: TokenStream) -> TokenStream {
},
};
let field_assignments: Vec<TokenStream2> = fields
// refinable_refine_assignments
// refinable_refined_assignments
// refinement_refine_assignments
let refineable_refine_assignments: Vec<TokenStream2> = fields
.iter()
.map(|field| {
let name = &field.ident;
@ -106,7 +110,34 @@ pub fn derive_refineable(input: TokenStream) -> TokenStream {
})
.collect();
let refinement_field_assignments: Vec<TokenStream2> = fields
let refineable_refined_assignments: Vec<TokenStream2> = fields
.iter()
.map(|field| {
let name = &field.ident;
let is_refineable = is_refineable_field(field);
let is_optional = is_optional_field(field);
if is_refineable {
quote! {
self.#name = self.#name.refined(refinement.#name);
}
} else if is_optional {
quote! {
if let Some(value) = refinement.#name {
self.#name = Some(value);
}
}
} else {
quote! {
if let Some(value) = refinement.#name {
self.#name = value;
}
}
}
})
.collect();
let refinement_refine_assigments: Vec<TokenStream2> = fields
.iter()
.map(|field| {
let name = &field.ident;
@ -126,6 +157,49 @@ pub fn derive_refineable(input: TokenStream) -> TokenStream {
})
.collect();
let refinement_refined_assigments: Vec<TokenStream2> = fields
.iter()
.map(|field| {
let name = &field.ident;
let is_refineable = is_refineable_field(field);
if is_refineable {
quote! {
self.#name = self.#name.refined(refinement.#name);
}
} else {
quote! {
if let Some(value) = refinement.#name {
self.#name = Some(value);
}
}
}
})
.collect();
let from_refinement_assigments: Vec<TokenStream2> = fields
.iter()
.map(|field| {
let name = &field.ident;
let is_refineable = is_refineable_field(field);
let is_optional = is_optional_field(field);
if is_refineable {
quote! {
#name: value.#name.into(),
}
} else if is_optional {
quote! {
#name: value.#name.map(|v| v.into()),
}
} else {
quote! {
#name: value.#name.map(|v| v.into()).unwrap_or_default(),
}
}
})
.collect();
let debug_impl = if impl_debug_on_refinement {
let refinement_field_debugs: Vec<TokenStream2> = fields
.iter()
@ -173,7 +247,12 @@ pub fn derive_refineable(input: TokenStream) -> TokenStream {
type Refinement = #refinement_ident #ty_generics;
fn refine(&mut self, refinement: &Self::Refinement) {
#( #field_assignments )*
#( #refineable_refine_assignments )*
}
fn refined(mut self, refinement: Self::Refinement) -> Self {
#( #refineable_refined_assignments )*
self
}
}
@ -183,7 +262,22 @@ pub fn derive_refineable(input: TokenStream) -> TokenStream {
type Refinement = #refinement_ident #ty_generics;
fn refine(&mut self, refinement: &Self::Refinement) {
#( #refinement_field_assignments )*
#( #refinement_refine_assigments )*
}
fn refined(mut self, refinement: Self::Refinement) -> Self {
#( #refinement_refined_assigments )*
self
}
}
impl #impl_generics From<#refinement_ident #ty_generics> for #ident #ty_generics
#where_clause
{
fn from(value: #refinement_ident #ty_generics) -> Self {
Self {
#( #from_refinement_assigments )*
}
}
}

View file

@ -4,24 +4,12 @@ pub trait Refineable: Clone {
type Refinement: Refineable<Refinement = Self::Refinement> + Default;
fn refine(&mut self, refinement: &Self::Refinement);
fn refined(mut self, refinement: &Self::Refinement) -> Self
where
Self: Sized,
{
self.refine(refinement);
self
}
fn from_refinement(refinement: &Self::Refinement) -> Self
where
Self: Default + Sized,
{
Self::default().refined(refinement)
}
fn refined(self, refinement: Self::Refinement) -> Self;
fn from_cascade(cascade: &Cascade<Self>) -> Self
where
Self: Default + Sized,
{
Self::default().refined(&cascade.merged())
Self::default().refined(cascade.merged())
}
}