diff options
| author | Mica White <botahamec@outlook.com> | 2026-09-24 20:59:43 -0400 |
|---|---|---|
| committer | Mica White <botahamec@outlook.com> | 2026-09-24 20:59:43 -0400 |
| commit | a08d9f1a1afa6ec11bcb99e29b030b1d3a44b63f (patch) | |
| tree | 8adc7b4c00e63a42e4d345f7b1725c81a2a0eb3f | |
| parent | 3b1549699693504382d9162d2bb1a73ac1eeccd9 (diff) | |
| -rw-r--r-- | Cargo.lock | 35 | ||||
| -rw-r--r-- | devenv.nix | 6 | ||||
| -rw-r--r-- | src/lib.rs | 35 | ||||
| -rw-r--r-- | tests/basic.rs | 9 |
4 files changed, 59 insertions, 26 deletions
@@ -13,7 +13,7 @@ dependencies = [ "manyhow", "proc-macro2", "quote", - "syn", + "syn 2.0.119", ] [[package]] @@ -29,7 +29,7 @@ dependencies = [ "proc-macro2", "quote", "quote-use", - "syn", + "syn 2.0.119", ] [[package]] @@ -40,13 +40,13 @@ checksum = "2550f75b8cfac212855f6b1885455df8eaee8fe8e246b647d69146142e016084" [[package]] name = "derive-where" -version = "1.6.1" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d08b3a0bcc0d079199cd476b2cae8435016ec11d1c0986c6901c5ac223041534" +checksum = "2e2b94854e8576378ccda7c8de8a66ed8b4e8acbd2c50ec3418ea6c8aaf4b567" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 3.0.6", ] [[package]] @@ -56,7 +56,7 @@ dependencies = [ "attribute-derive", "proc-macro2", "quote", - "syn", + "syn 2.0.119", ] [[package]] @@ -74,7 +74,7 @@ dependencies = [ "manyhow-macros", "proc-macro2", "quote", - "syn", + "syn 2.0.119", ] [[package]] @@ -136,14 +136,14 @@ dependencies = [ "proc-macro-utils", "proc-macro2", "quote", - "syn", + "syn 2.0.119", ] [[package]] name = "smallvec" -version = "1.15.2" +version = "1.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90" +checksum = "ba467056f1b547ed52077911161fc86985becbc60e8e1857c8a144dab0def891" [[package]] name = "syn" @@ -157,7 +157,18 @@ dependencies = [ ] [[package]] +name = "syn" +version = "3.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8593e8e72159ed2257d083c7a454a85cbf854f37a0966d8d483aff8c8a3ebcee" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] name = "unicode-ident" -version = "1.0.24" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" +checksum = "d245f478577f809a851594d02313b640fb437e0bb33866753cff937863096954" @@ -16,12 +16,6 @@ in cargo-seek cargo-nextest ]; - scripts.watcher = { - exec = '' - watchexec -c -e rs "cargo clippy && cargo test && cargo run" - ''; - packages = [ pkgs.watchexec ]; - }; enterShell = '' cargo update ''; @@ -293,6 +293,14 @@ pub fn derive_builder(input: TokenStream) -> TokenStream { #builder_macro + impl core::convert::From<#struct_name> for #builder_name<#(#trues),*> { + fn from(s: #struct_name) -> Self { + Self { + #(#field_names: Some(s.#field_names),)* + } + } + } + impl<#(const #const_generics: bool),*> core::default::Default for #builder_name<#(#const_generics),*> { fn default() -> Self { Self { @@ -305,6 +313,10 @@ pub fn derive_builder(input: TokenStream) -> TokenStream { #builder_visibility fn builder() -> #builder_name<#(#falses),*> { #builder_name::default() } + + #builder_visibility fn into_builder(self) -> #builder_name<#(#trues),*> { + #builder_name::from(self) + } } impl<#(const #const_generics: bool),*> #builder_name<#(#const_generics),*> { @@ -360,17 +372,28 @@ pub fn derive_builder(input: TokenStream) -> TokenStream { pub fn build(input: TokenStream) -> TokenStream { let structure = parse_macro_input!(input as ExprStruct); let struct_name = &structure.path; + let base = &structure.rest; let field_names = structure.fields.iter().map(|field| &field.member); let field_values = structure.fields.iter().map(|field| &field.expr); - quote! { - #struct_name - ::builder() - #(.#field_names(#field_values))* - .build() + if let Some(base) = base { + quote! { + #base + .into_builder() + #(.#field_names(#field_values))* + .build() + } + .into() + } else { + quote! { + #struct_name + ::builder() + #(.#field_names(#field_values))* + .build() + } + .into() } - .into() } /// Creates a declarative macro to construct a type that derives [`Builder`] diff --git a/tests/basic.rs b/tests/basic.rs index ce3abf8..52212d0 100644 --- a/tests/basic.rs +++ b/tests/basic.rs @@ -16,6 +16,8 @@ mod foo { use foo::Foo; +use crate::foo::FooBuild; + fn main() { let x = Foo::builder().baz(42).bar("hello").bat(5).build(); assert_eq!( @@ -27,8 +29,11 @@ fn main() { } ); - let bar = "hello"; - let _: Foo = Foo! { bar }; + let x: Foo = Foo! { + baz: 32, + bat: 64, + ..x + }; assert_eq!( x, Foo { |
