Skip to content

Commit ed9b18c

Browse files
authored
Add #[patch(empty_value=...)] (#134)
1 parent 542e43d commit ed9b18c

8 files changed

Lines changed: 311 additions & 59 deletions

File tree

.github/workflows/test.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,5 +62,7 @@ jobs:
6262
run: |
6363
nix develop .#ci -c cargo run --example status
6464
nix develop .#ci -c cargo run --example op
65+
nix develop .#ci -c cargo run --example clap
6566
nix develop .#ci -c cargo run --features=nesting --example nesting
67+
nix develop .#ci -c cargo run --features=nesting --example clap
6668
nix develop .#ci -c cargo test

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ members = [
77

88
[workspace.package]
99
authors = ["Antonio Yang <yanganto@gmail.com>"]
10-
version = "0.10.4"
10+
version = "0.10.5"
1111
edition = "2021"
1212
categories = ["development-tools"]
1313
keywords = ["struct", "patch", "macro", "derive", "overlay"]

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,9 @@ Field attributes:
110110
- `#[patch(name = "...")]`: change the type of the field in the generated patch struct.
111111
- `#[patch(attribute(...))]`: add attributes to the field in the generated patch struct.
112112
- `#[patch(attribute(derive(...)))]`: add derives to the field in the generated patch struct.
113+
- `#[patch(empty_value = ...)]`: define a value as empty, so the corresponding field of patch will not wrapped by Option, and apply patch when the field is empty.
113114
- `#[filler(extendable)]`: use the struct of field for filler, the struct needs implement `Default`, `Extend`, `IntoIterator` and `is_empty`.
114-
- `#[filler(empty_value)]`: define a value as empty, so the corresponding field of Filler will be applied, even the field is not `Option` or `Extendable`.
115+
- `#[filler(empty_value = ...)]`: define a value as empty, so the corresponding field of Filler will be applied, even the field is not `Option` or `Extendable`.
115116

116117
Please check the [traits][doc-traits] of document to learn more.
117118

derive/src/filler.rs

Lines changed: 3 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
use proc_macro2::{Ident, Span, TokenStream};
22
use quote::{quote, ToTokens};
33
use std::str::FromStr;
4-
use syn::meta::ParseNestedMeta;
5-
use syn::spanned::Spanned;
6-
use syn::{parenthesized, DeriveInput, Error, Lit, LitStr, Result, Type};
4+
use syn::{parenthesized, DeriveInput, Lit, LitStr, Result, Type};
75

86
#[cfg(feature = "op")]
97
use crate::Addable;
@@ -415,7 +413,7 @@ impl Field {
415413
return Err(meta
416414
.error("The field is already the field of filler, we can't defined more than once"));
417415
}
418-
if let Some(lit) = get_lit(path, &meta)? {
416+
if let Some(lit) = crate::get_lit(path, &meta)? {
419417
fty = Some(FillerType::NativeValue(lit));
420418
} else {
421419
return Err(meta
@@ -429,6 +427,7 @@ impl Field {
429427
}
430428
#[cfg(not(feature = "op"))]
431429
ADDABLE => {
430+
use syn::spanned::Spanned;
432431
return Err(syn::Error::new(
433432
ident.span(),
434433
"`addable` needs `op` feature",
@@ -501,22 +500,3 @@ fn none_option_filler_type(ty: &Type) -> Ident {
501500
panic!("#[filler(extendable)] should use on a type")
502501
}
503502
}
504-
505-
fn get_lit(attr_name: String, meta: &ParseNestedMeta) -> syn::Result<Option<syn::Lit>> {
506-
let expr: syn::Expr = meta.value()?.parse()?;
507-
let mut value = &expr;
508-
while let syn::Expr::Group(e) = value {
509-
value = &e.expr;
510-
}
511-
if let syn::Expr::Lit(syn::ExprLit { lit, .. }) = value {
512-
Ok(Some(lit.clone()))
513-
} else {
514-
Err(Error::new(
515-
expr.span(),
516-
format!(
517-
"expected serde {} attribute to be lit: `{} = \"...\"`",
518-
attr_name, attr_name
519-
),
520-
))
521-
}
522-
}

derive/src/lib.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ mod patch;
55
use filler::Filler;
66
use patch::Patch;
77

8+
use syn::meta::ParseNestedMeta;
9+
use syn::spanned::Spanned;
10+
use syn::Error;
11+
812
#[cfg(feature = "op")]
913
pub(crate) enum Addable {
1014
Disable,
@@ -29,3 +33,23 @@ pub fn derive_filler(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
2933
.unwrap()
3034
.into()
3135
}
36+
37+
fn get_lit(attr_name: String, meta: &ParseNestedMeta) -> syn::Result<Option<syn::Lit>> {
38+
let expr: syn::Expr = meta.value()?.parse()?;
39+
let mut value = &expr;
40+
while let syn::Expr::Group(e) = value {
41+
value = &e.expr;
42+
}
43+
if let syn::Expr::Lit(syn::ExprLit { lit, .. }) = value {
44+
Ok(Some(lit.clone()))
45+
} else {
46+
Err(Error::new(
47+
expr.span(),
48+
format!(
49+
"expected serde {} attribute to be lit: `{} = \"...\"`",
50+
attr_name, attr_name
51+
),
52+
))
53+
}
54+
}
55+

0 commit comments

Comments
 (0)