derive_builder_apply_to

Crates.ioderive_builder_apply_to
lib.rsderive_builder_apply_to
version0.1.0
created_at2025-07-27 05:21:20.948966+00
updated_at2025-07-27 05:21:20.948966+00
descriptionA procedural macro for generating apply_to methods for builder patterns
homepage
repository
max_upload_size
id1769727
size8,455
Carson Crane (cranium)

documentation

README

derive-builder-apply-to

A procedural macro for generating apply_to methods for builder patterns, designed to work seamlessly with the derive_builder crate.

Overview

The derive_builder crate is fantastic for creating new objects using the builder pattern. However, builders are typically used only for construction - once you call .build(), the builder is consumed.

This crate extends that functionality by allowing you to use builders to modify existing structs. Instead of building new objects, you can selectively update existing ones with only the fields you want to change.

This is especially useful for:

  • Partial updates in APIs (PATCH operations)
  • Configuration merging
  • Applying user preferences to default settings
  • Any scenario where you want to modify only specific fields

The ApplyTo derive macro generates an apply_to method on builder structs that:

  • Applies only the fields that have been explicitly set (non-None values)
  • Returns a boolean indicating whether any changes were made
  • Avoids unnecessary writes when values haven't changed

Usage

Add this to your Cargo.toml:

[dependencies]
derive_builder = "0.20"
derive-builder-apply-to = "0.1.0"

Then derive both Builder and ApplyTo on your struct:

use derive_builder::Builder;
use derive_builder_apply_to::ApplyTo;

#[derive(Builder, ApplyTo, Default, Debug, PartialEq)]
struct Person {
    name: String,
    age: u32,
    email: Option<String>,
}

fn main() {
    // Create an existing person
    let mut person = Person {
        name: "Alice".to_string(),
        age: 30,
        email: Some("alice@example.com".to_string()),
    };
    
    // Use builder to apply updates directly - no .build() needed!
    let changed = PersonBuilder::default()
        .age(31)
        .email(Some("alice.smith@example.com".to_string()))
        .apply_to(&mut person);
    
    assert!(changed);
    assert_eq!(person.name, "Alice"); // unchanged
    assert_eq!(person.age, 31);       // updated
    assert_eq!(person.email, Some("alice.smith@example.com".to_string())); // updated
    
    // Applying the same values again returns false
    let changed = PersonBuilder::default()
        .age(31)
        .apply_to(&mut person);
    assert!(!changed); // No change since age was already 31
}

How it works

The ApplyTo derive macro:

  1. Inspects your struct's fields
  2. Generates an apply_to method on the corresponding builder struct (e.g., PersonBuilder)
  3. The method iterates through each Option<T> field in the builder
  4. For each Some(value), it compares with the target struct's field
  5. Updates the target field only if the value is different
  6. Returns true if any field was changed, false otherwise

Requirements

  • Your struct must work with derive_builder (named fields only)
  • Field types must implement PartialEq for change detection
  • The builder struct must have Option<T> fields for optional updates

License

Licensed under the MIT License.

Commit count: 0

cargo fmt