Skip to content

Commit 2656e13

Browse files
committed
define empty value for native type
1 parent 9ba53ef commit 2656e13

File tree

2 files changed

+92
-6
lines changed

2 files changed

+92
-6
lines changed

struct-patch-derive/src/filler.rs

+77-5
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
use proc_macro2::{Ident, Span, TokenStream};
22
use quote::{quote, ToTokens};
33
use std::str::FromStr;
4-
use syn::{parenthesized, DeriveInput, LitStr, Result, Type};
4+
use syn::meta::ParseNestedMeta;
5+
use syn::spanned::Spanned;
6+
use syn::{parenthesized, DeriveInput, Error, Lit, LitStr, Result, Type};
57

68
const FILLER: &str = "filler";
79
const ATTRIBUTE: &str = "attribute";
810
const EXTENDABLE: &str = "extendable";
11+
const EMPTY_VALUE: &str = "empty_value";
912

1013
pub(crate) struct Filler {
1114
visibility: syn::Visibility,
@@ -16,18 +19,28 @@ pub(crate) struct Filler {
1619
fields: Vec<Field>,
1720
}
1821

19-
#[derive(Debug, PartialEq)]
22+
#[derive(PartialEq)]
2023
enum FillerType {
2124
Option,
25+
/// The type with `Default`, `Extend`, `IntoIterator` and `is_empty` implementations
2226
Extendable(Ident),
27+
/// The type defined a value for empty
28+
NativeValue(Lit),
2329
}
2430

2531
impl FillerType {
2632
fn inner(&self) -> &Ident {
2733
if let FillerType::Extendable(ident) = self {
2834
ident
2935
} else {
30-
panic!("FillerType::Option has no inner indent")
36+
panic!("Only FillerType::Extendable has inner indent")
37+
}
38+
}
39+
fn value(&self) -> &Lit {
40+
if let FillerType::NativeValue(lit) = self {
41+
lit
42+
} else {
43+
panic!("Only FillerType::NativeValue has value")
3144
}
3245
}
3346
}
@@ -74,6 +87,18 @@ impl Filler {
7487
.map(|f| f.fty.inner())
7588
.collect::<Vec<_>>();
7689

90+
let native_value_field_names = fields
91+
.iter()
92+
.filter(|f| matches!(f.fty, FillerType::NativeValue(_)))
93+
.map(|f| f.ident.as_ref())
94+
.collect::<Vec<_>>();
95+
96+
let native_value_field_values = fields
97+
.iter()
98+
.filter(|f| matches!(f.fty, FillerType::NativeValue(_)))
99+
.map(|f| f.fty.value())
100+
.collect::<Vec<_>>();
101+
77102
let mapped_attributes = attributes
78103
.iter()
79104
.map(|a| {
@@ -105,6 +130,11 @@ impl Filler {
105130
return false
106131
}
107132
)*
133+
#(
134+
if self.#native_value_field_names != #native_value_field_values {
135+
return false
136+
}
137+
)*
108138
true
109139
}
110140
}
@@ -115,6 +145,11 @@ impl Filler {
115145
let filler_impl = quote! {
116146
impl #generics struct_patch::traits::Filler< #name #generics > for #struct_name #generics #where_clause {
117147
fn apply(&mut self, filler: #name #generics) {
148+
#(
149+
if self.#native_value_field_names == #native_value_field_values {
150+
self.#native_value_field_names = filler.#native_value_field_names;
151+
}
152+
)*
118153
#(
119154
if self.#extendable_field_names.is_empty() {
120155
self.#extendable_field_names.extend(filler.#extendable_field_names.into_iter());
@@ -133,6 +168,7 @@ impl Filler {
133168
#name {
134169
#(#option_field_names: None,)*
135170
#(#extendable_field_names: #extendable_field_types::default(),)*
171+
#(#native_value_field_names: #native_value_field_values,)*
136172
}
137173
}
138174
}
@@ -282,7 +318,24 @@ impl Field {
282318
}
283319
EXTENDABLE => {
284320
// #[filler(extendable)]
285-
fty = Some(FillerType::Extendable(extendable_filler_type(&ty)));
321+
if fty.is_some() {
322+
return Err(meta
323+
.error("The field is already the field of filler, we can't defined more than once"));
324+
}
325+
fty = Some(FillerType::Extendable(none_option_filler_type(&ty)));
326+
}
327+
EMPTY_VALUE => {
328+
// #[filler(empty_value=some value)]
329+
if fty.is_some() {
330+
return Err(meta
331+
.error("The field is already the field of filler, we can't defined more than once"));
332+
}
333+
if let Some(lit) = get_lit(path, &meta)? {
334+
fty = Some(FillerType::NativeValue(lit));
335+
} else {
336+
return Err(meta
337+
.error("empty_value needs a clear value to define empty"));
338+
}
286339
}
287340
_ => {
288341
return Err(meta.error(format_args!(
@@ -342,10 +395,29 @@ fn filler_type(ty: &Type) -> Option<FillerType> {
342395
None
343396
}
344397

345-
fn extendable_filler_type(ty: &Type) -> Ident {
398+
fn none_option_filler_type(ty: &Type) -> Ident {
346399
if let Type::Path(type_path) = ty {
347400
type_path.path.segments[0].ident.clone()
348401
} else {
349402
panic!("#[filler(extendable)] should use on a type")
350403
}
351404
}
405+
406+
fn get_lit(attr_name: String, meta: &ParseNestedMeta) -> syn::Result<Option<syn::Lit>> {
407+
let expr: syn::Expr = meta.value()?.parse()?;
408+
let mut value = &expr;
409+
while let syn::Expr::Group(e) = value {
410+
value = &e.expr;
411+
}
412+
if let syn::Expr::Lit(syn::ExprLit { lit, .. }) = value {
413+
Ok(Some(lit.clone()))
414+
} else {
415+
Err(Error::new(
416+
expr.span(),
417+
format!(
418+
"expected serde {} attribute to be lit: `{} = \"...\"`",
419+
attr_name, attr_name
420+
),
421+
))
422+
}
423+
}

struct-patch/examples/filler.rs

+15-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,11 @@ impl WrapVec {
3434
#[filler(attribute(derive(Debug, Default)))]
3535
struct Item {
3636
field_complete: bool,
37+
// Will check the field is equal to the value to define the field is empty or not
38+
#[filler(empty_value = 0)]
3739
field_int: usize,
40+
// Will check the field is equal to String::default() to define the field is empty or not
41+
// #[filler(empty=default)]
3842
field_string: String,
3943
maybe_field_int: Option<usize>,
4044
maybe_field_string: Option<String>,
@@ -81,7 +85,7 @@ fn main() {
8185

8286
assert_eq!(
8387
format!("{filler:?}"),
84-
"ItemFiller { maybe_field_int: Some(7), maybe_field_string: None, list: [], _deque: [], _linked_list: [], _set: {}, _bset: {}, _heap: [], _wrap: WrapVec { inner: [] } }"
88+
"ItemFiller { field_int: 0, maybe_field_int: Some(7), maybe_field_string: None, list: [], _deque: [], _linked_list: [], _set: {}, _bset: {}, _heap: [], _wrap: WrapVec { inner: [] } }"
8589
);
8690

8791
item.apply(filler);
@@ -115,4 +119,14 @@ fn main() {
115119
filler.list = vec![3, 4];
116120
item.apply(filler);
117121
assert_eq!(item.list, vec![1, 2]);
122+
123+
let mut filler: ItemFiller = Item::new_empty_filler();
124+
filler.field_int = 7;
125+
item.apply(filler);
126+
assert_eq!(item.field_int, 7);
127+
128+
let mut filler: ItemFiller = Item::new_empty_filler();
129+
filler.field_int = 5;
130+
item.apply(filler);
131+
assert_eq!(item.field_int, 7);
118132
}

0 commit comments

Comments
 (0)