# Former Crate - Advanced Usage and Concepts
This document provides detailed explanations of the advanced features, customization options, and underlying concepts of the `former` crate. It assumes you have a basic understanding of how to use `#[ derive( Former ) ]` as covered in the main [Readme.md](./Readme.md).
## Struct/Enum Level Attributes
Applied directly above the `struct` or `enum` definition.
* **`#[ storage_fields( field_name : FieldType, ... ) ]`**
* Defines extra fields exclusive to the temporary `...FormerStorage` struct.
* **`#[ mutator( custom ) ]`**
* Disables automatic generation of the default `impl former::FormerMutator`, requiring a manual implementation.
* **`#[ perform( fn method_name<...> () -> OutputType ) ]`**
* Specifies a method on the original struct to be called by the former's `.perform()` method after forming the struct instance.
## Field Level Attributes
Applied directly above fields within a struct.
**General Field Control:**
* **`#[ former( default = value ) ]`**
* Provides a default `value` for the field if its setter is not called.
**Scalar Field Control:**
* **`#[ scalar ]`** (Often implicit for simple fields)
* Generates a standard setter method (`.field_name(value)`).
* **Arguments:**
* `name = new_name`: Renames the setter method (e.g., `#[ scalar( name = first_field ) ]`).
* `setter = bool`: Explicitly enables/disables setter generation (e.g., `#[ scalar( setter = false ) ]`). Default: `true`.
**Subformer Field Control (for nested building):**
* **`#[ subform_collection ]`** (For `Vec`, `HashMap`, `HashSet`, etc.)
* Generates a method returning a collection-specific subformer (e.g., `.field_name().add(item).end()`).
* **Arguments:**
* `definition = path::to::CollectionDefinition`: Specifies the collection type (e.g., `#[ subform_collection( definition = former::VectorDefinition ) ]`). Often inferred.
* `name = new_name`: Renames the subformer starter method (e.g., `#[ subform_collection( name = children2 ) ]`).
* `setter = bool`: Enables/disables the subformer starter method (e.g., `#[ subform_collection( setter = false ) ]`). Default: `true`.
* **`#[ subform_entry ]`** (For collections where entries are built individually)
* Generates a method returning a subformer for a *single entry* of the collection (e.g., `.field_name().entry_field(val).end()`).
* **Arguments:**
* `name = new_name`: Renames the entry subformer starter method (e.g., `#[ subform_entry( name = _child ) ]`).
* `setter = bool`: Enables/disables the entry subformer starter method (e.g., `#[ subform_entry( setter = false ) ]`). Default: `true`.
* **`#[ subform_scalar ]`** (For fields whose type also derives `Former`)
* Generates a method returning a subformer for the nested struct (e.g., `.field_name().inner_field(val).end()`).
* **Arguments:**
* `name = new_name`: Renames the subformer starter method (e.g., `#[ subform_scalar( name = child2 ) ]`).
* `setter = bool`: (Likely) Enables/disables the subformer starter method. Default: `true`.
## Core Concepts Deep Dive
Understanding the components generated by `#[ derive( Former ) ]` helps in customizing the builder pattern effectively.
### Storage (`...FormerStorage`)
When you derive `Former` for a struct like `MyStruct`, a corresponding storage struct, typically named `MyStructFormerStorage`, is generated internally.
* **Purpose:** This storage struct acts as a temporary container holding the intermediate state of the object during its construction via the former.
* **Fields:** It contains fields corresponding to the original struct's fields, but wrapped in `Option`. For example, a field `my_field : i32` in `MyStruct` becomes `pub my_field : Option< i32 >` in `MyStructFormerStorage`. This allows the former to track which fields have been explicitly set. Optional fields in the original struct (e.g., `my_option : Option< String >`) remain `Option< String >` in the storage.
* **Storage-Only Fields:** If you use the `#[ storage_fields( ... ) ]` attribute on the struct, those additional fields are *only* present in the storage struct, not in the final formed struct. This is useful for temporary calculations or state needed during the building process.
* **Decoupling:** The storage struct decouples the configuration steps (calling setters) from the final object instantiation (`.form()` or `.end()`). You can call setters in any order.
* **Finalization:** When `.form()` or `.end()` is called, the `StoragePreform::preform` method is invoked on the storage struct. This method consumes the storage, unwraps the `Option`s for required fields (panicking or using defaults if not set), handles optional fields appropriately, and constructs the final struct instance (`MyStruct`).
The `...Former` struct itself holds an instance of this `...FormerStorage` struct internally to manage the building process.
### Definitions (`...Definition`, `...DefinitionTypes`)
Alongside the `Former` and `Storage` structs, the derive macro also generates two definition structs: `...FormerDefinitionTypes` and `...FormerDefinition`.
* **`...FormerDefinitionTypes`:**
* **Purpose:** Defines the core *types* involved in the formation process for a specific entity.
* **Associated Types:**
* `Storage`: Specifies the storage struct used (e.g., `MyStructFormerStorage`).
* `Formed`: Specifies the type that is ultimately produced by the `.form()` or `.end()` methods. By default, this is the original struct (e.g., `MyStruct`), but it can be changed by custom `FormingEnd` implementations.
* `Context`: Specifies the type of contextual information passed down during subforming (if the former is used as a subformer). Defaults to `()`.
* **Traits:** Implements `former_types::FormerDefinitionTypes` and `former_types::FormerMutator`.
* **`...FormerDefinition`:**
* **Purpose:** Extends `...FormerDefinitionTypes` by adding the *end condition* logic. It fully defines how a former behaves.
* **Associated Types:** Inherits `Storage`, `Formed`, `Context`, and `Types` (which points back to the `...FormerDefinitionTypes` struct) from the `former_types::FormerDefinition` trait.
* **`End` Associated Type:** Specifies the type that implements the `former_types::FormingEnd` trait, defining what happens when `.form()` or `.end()` is called. This defaults to `former_types::ReturnPreformed` (which calls `StoragePreform::preform` on the storage) but can be customized.
* **Traits:** Implements `former_types::FormerDefinition`.
* **Role in Generics:** The `Definition` generic parameter on the `...Former` struct (e.g., `MyStructFormer< Definition = ... >`) allows customizing the entire forming behavior by providing a different `FormerDefinition` implementation. This enables advanced scenarios like changing the formed type or altering the end-of-forming logic.
In most basic use cases, you don't interact with these definition structs directly, but they underpin the flexibility and customization capabilities of the `former` crate, especially when dealing with subformers and custom end logic.
### Context
The `Context` is an optional piece of data associated with a `Former`. It plays a crucial role primarily when a `Former` is used as a **subformer** (i.e., when building a nested struct or collection entries).
* **Purpose:** To pass information or state *down* from a parent former to its child subformer during the building process.
* **Default:** For a top-level former (one created directly via `MyStruct::former()`), the context type defaults to `()` (the unit type), and the context value is `None`.
* **Subforming:** When a subformer is initiated (e.g., by calling `.my_subform_field()` on a parent former), the parent former typically passes *itself* as the context to the subformer.
* **`FormingEnd` Interaction:** The `FormingEnd::call` method receives the context (`Option< Context >`) as its second argument. When a subformer finishes (via `.end()`), its `FormingEnd` implementation usually receives the parent former (`Some( parent_former )`) as the context. This allows the `End` logic to:
1. Retrieve the formed value from the subformer's storage.
2. Modify the parent former's storage (e.g., insert the formed value into the parent's collection or field).
3. Return the modified parent former to continue the building chain.
* **Customization:** While the default context is `()` or the parent former, you can define custom formers and `FormingEnd` implementations that use different context types to pass arbitrary data relevant to the specific building logic.
In essence, the context provides the mechanism for subformers to communicate back and integrate their results into their parent former upon completion.
### End Condition (`FormingEnd`, `ReturnStorage`, `ReturnPreformed`, Closures)
The `End` condition determines what happens when the forming process is finalized by calling `.form()` or `.end()` on a `Former`. It's defined by the `End` associated type within the `FormerDefinition` and must implement the `former_types::FormingEnd` trait.
* **`FormingEnd` Trait:**
* Defines a single method: `call( &self, storage : Definition::Storage, context : Option< Definition::Context > ) -> Definition::Formed`.
* This method consumes the `storage` and optional `context` and produces the final `Formed` type.
* **Default End Conditions (Provided by `former_types`):**
* **`ReturnPreformed`:** This is the default `End` type for formers generated by `#[ derive( Former ) ]`. Its `call` implementation invokes `StoragePreform::preform` on the storage, effectively unwrapping `Option`s, applying defaults, and constructing the final struct instance. It ignores the context. The `Formed` type is the original struct type.
* **`ReturnStorage`:** A simpler `End` type often used for collection formers. Its `call` implementation simply returns the storage itself *without* calling `preform`. The `Formed` type is the same as the `Storage` type (e.g., `Vec< T >`, `HashMap< K, V >`). It also ignores the context.
* **`NoEnd`:** A placeholder that panics if `call` is invoked. Useful in generic contexts where an `End` type is required syntactically but never actually used.
* **Subformer End Conditions (Generated by `#[ derive( Former ) ]`):**
* When you use subform attributes (`#[ subform_scalar ]`, `#[ subform_collection ]`, `#[ subform_entry ]`), the derive macro generates specialized internal `End` structs (e.g., `ParentFormerSubformScalarChildEnd`).
* The `call` implementation for these generated `End` structs typically:
1. Takes the subformer's `storage` and the parent former as `context`.
2. Calls `StoragePreform::preform` on the subformer's storage to get the formed value (e.g., the `Child` instance or the `Vec< Child >`).
3. Assigns this formed value to the appropriate field in the parent former's storage (retrieved from the `context`).
4. Returns the modified parent former (`Formed` type is the parent former).
* **Custom End Conditions (Closures & Structs):**
* You can provide a custom closure or a struct implementing `FormingEnd` when manually constructing a former using methods like `Former::begin`, `Former::new`, or their `_coercing` variants.
* This allows you to define arbitrary logic for the finalization step, such as:
* Performing complex validation on the storage before forming.
* Transforming the storage into a different `Formed` type.
* Integrating the result into a custom context.
* `former_types::FormingEndClosure` is a helper to easily wrap a closure for use as an `End` type.
The `End` condition provides the final hook for controlling the transformation from the intermediate storage state to the desired final output of the forming process.
### Mutators (`FormerMutator`, `#[mutator(custom)]`)
The `FormerMutator` trait provides an optional hook to modify the `Storage` and `Context` *just before* the `FormingEnd::call` method is invoked during the finalization step (`.form()` or `.end()`).
* **Purpose:** To perform last-minute adjustments, calculations, or conditional logic based on the accumulated state in the storage *before* the final transformation into the `Formed` type occurs. This is particularly useful for:
* Setting derived fields based on other fields set during the building process.
* Applying complex validation logic that depends on multiple fields.
* Making use of `#[ storage_fields( ... ) ]` to compute final values for the actual struct fields.
* **`FormerMutator` Trait:**
* Associated with the `...FormerDefinitionTypes` struct.
* Defines one method: `form_mutation( storage: &mut Self::Storage, context: &mut Option< Self::Context > )`.
* This method receives *mutable* references, allowing direct modification of the storage and context.
* **Default Behavior:** By default, `#[ derive( Former ) ]` generates an empty `impl FormerMutator` for the `...FormerDefinitionTypes`. This means no mutation occurs unless customized.
* **Customization (`#[ mutator( custom ) ]`):**
* Applying `#[ mutator( custom ) ]` to the struct tells the derive macro *not* to generate the default empty implementation.
* You must then provide your own `impl FormerMutator for YourStructFormerDefinitionTypes< ... > { ... }` block, implementing the `form_mutation` method with your custom logic.
* **Execution Order:** `FormerMutator::form_mutation` runs *after* the user calls `.form()` or `.end()` but *before* `FormingEnd::call` is executed.
* **vs. `FormingEnd`:** While `FormingEnd` defines the *final transformation* from storage to the formed type, `FormerMutator` allows *intermediate modification* of the storage/context just prior to that final step. It's useful when the logic depends on the builder's state but shouldn't be part of the final type conversion itself.
[See Example: Mutator and Storage Fields](https://github.com/Wandalen/wTools/blob/master/module/core/former/examples/former_custom_mutator.rs)
## Subformer Types In Detail
Subformers are a key feature of the `former` crate, enabling the construction of nested data structures and collections in a fluent manner. Different attributes control how subformers are generated and behave.
### `#[ subform_scalar ]` - Building Nested Structs
Use the `#[ subform_scalar ]` attribute on a field whose type *also* derives `Former`. This generates a setter method that returns the dedicated `Former` for that field's type, allowing you to configure the nested struct within the parent's builder chain.
* **Attribute:** `#[ subform_scalar ]` (applied to the field in the parent struct)
* **Requirement:** The field's type (e.g., `Child` in `parent_field: Child`) must derive `Former`.
* **Generated Setter:** By default, a method with the same name as the field (e.g., `.child()`) is generated on the parent's former (`ParentFormer`). This method returns the child's former (`ChildFormer`).
* **Usage:**
```rust
parent_former
.child() .child_field1(...)
.child_field2(...)
.end() .form() ```
* **`End` Condition:** The derive macro automatically generates a specialized `End` struct (e.g., `ParentFormerSubformScalarChildEnd`) for the subformer. When `.end()` is called on the subformer (`ChildFormer`), this `End` struct's `call` method takes the finalized `Child` storage, preforms it into a `Child` instance, assigns it to the `child` field in the parent's storage (passed via context), and returns the parent former.
* **Customization:**
* `#[ subform_scalar( name = new_setter_name ) ]`: Renames the generated setter method (e.g., `.child_alt()` instead of `.child()`).
* `#[ subform_scalar( setter = false ) ]`: Disables the generation of the user-facing setter method (`.child()`). However, it still generates the internal helper method (e.g., `._child_subform_scalar()`) and the `End` struct, allowing you to create custom setters with different arguments while reusing the core subforming logic.
**Example:**
```rust
# #[ cfg( not( all( feature = "enabled", feature = "derive_former", any( feature = "use_alloc",not( feature = "no_std" ) ) ) ) ) ]
# fn main() {}
# #[ cfg( all( feature = "enabled", feature = "derive_former", any( feature = "use_alloc",not( feature = "no_std" ) ) ) ) ]
# fn main()
# {
use former::Former;
#[ derive( Debug, Default, PartialEq, Former ) ]
pub struct Address
{
street : String,
city : String,
}
#[ derive( Debug, Default, PartialEq, Former ) ]
pub struct User
{
name : String,
#[ subform_scalar ] // Use subformer for the 'address' field
address : Address,
}
let user = User::former()
.name( "Alice".to_string() )
.address() // Returns AddressFormer< UserFormer, ... >
.street( "123 Main St".to_string() )
.city( "Anytown".to_string() )
.end() // Finalizes Address, returns UserFormer
.form(); // Finalizes User
assert_eq!( user.name, "Alice" );
assert_eq!( user.address.street, "123 Main St" );
assert_eq!( user.address.city, "Anytown" );
# }
```
[See full example code](https://github.com/Wandalen/wTools/blob/master/module/core/former/examples/former_custom_subform_scalar.rs)
### `#[ subform_collection ]` - Building Collections Fluently
Use the `#[ subform_collection ]` attribute on fields that represent collections like `Vec< E >`, `HashMap< K, V >`, `HashSet< K >`, etc. This generates a setter method that returns a specialized **collection former** tailored to the specific collection type, allowing you to add multiple elements fluently.
* **Attribute:** `#[ subform_collection ]` (applied to the collection field)
* **Requirement:** The field type must be a collection type for which `former` has built-in support (e.g., `Vec`, `HashMap`, `HashSet`, `BTreeMap`, `BTreeSet`, `LinkedList`, `BinaryHeap`) or a custom type that implements the necessary `former_types::Collection` traits.
* **Generated Setter:** By default, a method with the same name as the field (e.g., `.entries()`) is generated. This method returns a `former_types::CollectionFormer` instance specialized for the field's collection type (e.g., `VectorFormer`, `HashMapFormer`).
* **Usage:**
```rust
parent_former
.entries() .add( "item1".to_string() ) .add( "item2".to_string() )
.end() .form() ```
* **Collection Methods:** The returned collection former provides methods like `.add( entry )` and `.replace( iterator )`. The exact type of `entry` depends on the collection (`E` for `Vec`/`HashSet`, `( K, V )` for `HashMap`).
* **`End` Condition:** Similar to `subform_scalar`, the derive macro generates a specialized `End` struct (e.g., `ParentSubformCollectionEntriesEnd`). Its `call` method takes the subformer's storage (the collection being built), assigns it to the corresponding field in the parent former's storage, and returns the parent former.
* **Customization:**
* `#[ subform_collection( name = new_setter_name ) ]`: Renames the generated setter method.
* `#[ subform_collection( setter = false ) ]`: Disables the user-facing setter, but still generates the internal helper (`._entries_subform_collection()`) and `End` struct for custom setter implementation.
* `#[ subform_collection( definition = MyCollectionDefinition ) ]`: Specifies a custom `FormerDefinition` to use for the collection, overriding the default behavior (useful for custom collection types or specialized logic).
**Example (Vec):**
```rust
# #[ cfg( not( all( feature = "enabled", feature = "derive_former", any( feature = "use_alloc", not( feature = "no_std" ) ) ) ) ) ]
# fn main() {}
# #[ cfg( all( feature = "enabled", feature = "derive_former", any( feature = "use_alloc", not( feature = "no_std" ) ) ) ) ]
# fn main()
# {
use former::Former;
use std::collections::VecDeque; // Example using VecDeque
#[ derive( Debug, PartialEq, Former ) ]
pub struct DataPacket
{
id : u32,
#[ subform_collection ] // Uses default VectorDefinition for Vec
// #[ subform_collection( definition = former::VecDequeDefinition ) ] // Example for VecDeque
payload : Vec< u8 >,
// payload : VecDeque< u8 >, // Alternative
}
let packet = DataPacket::former()
.id( 101 )
.payload() // Returns VectorFormer< u8, ... >
.add( 0xDE )
.add( 0xAD )
.add( 0xBE )
.add( 0xEF )
.end()
.form();
assert_eq!( packet.id, 101 );
assert_eq!( packet.payload, vec![ 0xDE, 0xAD, 0xBE, 0xEF ] );
# }
```
### `#[ subform_entry ]` - Building Collection Entries Individually
Use the `#[ subform_entry ]` attribute on collection fields (like `Vec< Child >` or `HashMap< String, Child >`) where each *entry* of the collection should be built using its own dedicated `Former`. This is ideal when the elements themselves are complex structs requiring configuration.
* **Attribute:** `#[ subform_entry ]` (applied to the collection field)
* **Requirement:** The *value type* of the collection entry (e.g., `Child` in `Vec< Child >` or `HashMap< K, Child >`) must derive `Former`. For map types, the value type must also implement `former_types::ValToEntry< CollectionType >` to specify how a formed value maps back to a key-value pair entry.
* **Generated Setter:** By default, a method with the same name as the field (e.g., `.child()`) is generated. This method returns the `Former` for the *entry type* (e.g., `ChildFormer`).
* **Usage:**
```rust
parent_former
.child() .child_field1(...)
.child_field2(...)
.end() .child() .end() .form() ```
* **`End` Condition:** The derive macro generates a specialized `End` struct (e.g., `ParentSubformEntryChildrenEnd`). When `.end()` is called on the entry's former (`ChildFormer`), this `End` struct's `call` method takes the `Child` storage, preforms it into a `Child` instance, potentially converts it to the collection's `Entry` type (using `ValToEntry` for maps), adds the entry to the parent's collection field (passed via context), and returns the parent former.
* **Customization:**
* `#[ subform_entry( name = new_setter_name ) ]`: Renames the generated setter method.
* `#[ subform_entry( setter = false ) ]`: Disables the user-facing setter, but still generates the internal helper (`._children_subform_entry()`) and `End` struct for custom setter implementation (e.g., to pass arguments like a key for a map).
**Example (HashMap):**
```rust
# #[ cfg( not( all( feature = "enabled", feature = "derive_former", any( feature = "use_alloc", not( feature = "no_std" ) ) ) ) ) ]
# fn main() {}
# #[ cfg( all( feature = "enabled", feature = "derive_former", any( feature = "use_alloc", not( feature = "no_std" ) ) ) ) ]
# fn main()
# {
use former::Former;
use std::collections::HashMap;
use former::ValToEntry; // Needed for HashMap entry conversion
#[ derive( Debug, Default, PartialEq, Clone, Former ) ]
pub struct Command
{
name : String,
description : String,
}
// Required to map the formed `Command` back to a (key, value) pair for the HashMap
impl ValToEntry< HashMap< String, Command > > for Command
{
type Entry = ( String, Command );
#[ inline( always ) ]
fn val_to_entry( self ) -> Self::Entry
{
( self.name.clone(), self )
}
}
#[ derive( Debug, Default, PartialEq, Former ) ]
pub struct CommandRegistry
{
#[ subform_entry ] // Each command will be built using CommandFormer
commands : HashMap< String, Command >,
}
let registry = CommandRegistry::former()
.commands() // Returns CommandFormer< CommandRegistryFormer, ... >
.name( "help".to_string() )
.description( "Shows help".to_string() )
.end() // Forms Command, adds ("help", Command{...}) to map, returns CommandRegistryFormer
.commands() // Start next command
.name( "run".to_string() )
.description( "Runs the task".to_string() )
.end() // Forms Command, adds ("run", Command{...}) to map, returns CommandRegistryFormer
.form(); // Finalizes CommandRegistry
assert_eq!( registry.commands.len(), 2 );
assert!( registry.commands.contains_key( "help" ) );
assert_eq!( registry.commands[ "run" ].description, "Runs the task" );
# }
```
[See HashMap example](https://github.com/Wandalen/wTools/blob/master/module/core/former/examples/former_custom_subform_entry.rs) | [See Vec example](https://github.com/Wandalen/wTools/blob/master/module/core/former/tests/inc/struct_tests/subform_entry.rs)
## Customization
The `former` crate offers several ways to customize the generated builder beyond the standard setters and subformers.
### Custom Setters (Alternative and Overriding)
You can define your own setter methods directly within an `impl` block for the generated `...Former` struct.
* **Alternative Setters:** Define methods with different names that perform custom logic before setting the value in the former's storage. This allows for preprocessing or validation specific to that setter.
```rust
# #[ cfg( any( not( feature = "derive_former" ), not( feature = "enabled" ) ) ) ]
# fn main() {}
# #[ cfg( all( feature = "derive_former", feature = "enabled" ) ) ]
# fn main()
# {
use former::Former;
#[ derive( Debug, Former ) ]
pub struct MyStruct
{
word : String,
}
impl MyStructFormer {
pub fn word_exclaimed( mut self, value : impl Into< String > ) -> Self
{
debug_assert!( self.storage.word.is_none(), "Field 'word' was already set" );
self.storage.word = Some( format!( "{}!", value.into() ) );
self
}
}
let s1 = MyStruct::former().word( "Hello" ).form();
assert_eq!( s1.word, "Hello" );
let s2 = MyStruct::former().word_exclaimed( "Hello" ).form();
assert_eq!( s2.word, "Hello!" );
# }
```
[See full example code](https://github.com/Wandalen/wTools/blob/master/module/core/former/examples/former_custom_setter.rs)
* **Overriding Setters:** You can completely replace the default generated setter by:
1. Disabling the default setter using `#[ scalar( setter = false ) ]` (or `subform_... ( setter = false )`).
2. Implementing a method with the *original* field name on the `...Former` struct.
```rust
# #[ cfg( any( not( feature = "derive_former" ), not( feature = "enabled" ) ) ) ]
# fn main() {}
# #[ cfg( all( feature = "derive_former", feature = "enabled" ) ) ]
# fn main()
# {
use former::Former;
#[ derive( Debug, Former ) ]
pub struct MyStruct
{
#[ scalar( setter = false ) ] word : String,
}
impl< Definition > MyStructFormer< Definition >
where
Definition : former::FormerDefinition< Storage = MyStructFormerStorage >,
{
#[ inline ]
pub fn word< Src >( mut self, src : Src ) -> Self
where
Src : ::core::convert::Into< String >,
{
debug_assert!( self.storage.word.is_none() );
self.storage.word = Some( format!( "{}!", src.into() ) );
self
}
}
let s1 = MyStruct::former().word( "Hello" ).form();
assert_eq!( s1.word, "Hello!" );
# }
```
[See full example code](https://github.com/Wandalen/wTools/blob/master/module/core/former/examples/former_custom_setter_overriden.rs)
### Custom Defaults (`#[ former( default = ... ) ]`)
While `former` automatically uses `Default::default()` for fields that are not explicitly set, you can specify a *different* default value using the `#[ former( default = ... ) ]` attribute on a field.
* **Purpose:**
* Provide a default for types that do not implement `Default`.
* Specify a non-standard default value (e.g., `true` for a `bool`, or a specific number).
* Initialize collections with default elements.
* **Usage:** Apply the attribute directly to the field, providing a valid Rust expression as the default value.
* **Behavior:** If the field's setter is *not* called during the building process, the expression provided in `default = ...` will be evaluated and used when `.form()` or `.end()` is called. If the setter *is* called, the attribute's default is ignored.
**Example:**
```rust
# #[ cfg( any( not( feature = "derive_former" ), not( feature = "enabled" ) ) ) ]
# fn main() {}
# #[ cfg( all( feature = "derive_former", feature = "enabled" ) ) ]
# fn main()
# {
use former::Former;
#[ derive( Debug, PartialEq, Former ) ]
pub struct NetworkConfig
{
#[ former( default = 8080 ) ] // Default port if not specified
port : u16,
#[ former( default = "127.0.0.1".to_string() ) ] // Default host
host : String,
#[ former( default = vec![ "admin".to_string() ] ) ] // Default users
initial_users : Vec< String >,
timeout : Option< u32 >, // Optional, defaults to None
}
// Form without setting port, host, or initial_users
let config = NetworkConfig::former()
.timeout( 5000 ) // Only set timeout
.form();
assert_eq!( config.port, 8080 );
assert_eq!( config.host, "127.0.0.1" );
assert_eq!( config.initial_users, vec![ "admin".to_string() ] );
assert_eq!( config.timeout, Some( 5000 ) );
# }
```
[See full example code](https://github.com/Wandalen/wTools/blob/master/module/core/former/examples/former_custom_defaults.rs)
### Storage-Specific Fields (`#[ storage_fields( ... ) ]`)
Sometimes, the building process requires temporary data or intermediate calculations that shouldn't be part of the final struct. The `#[ storage_fields( ... ) ]` attribute allows you to define fields that exist *only* within the generated `...FormerStorage` struct.
* **Purpose:**
* Store temporary state needed during building (e.g., flags, counters).
* Accumulate data used to calculate a final field value within a `Mutator`.
* Hold configuration that influences multiple final fields.
* **Usage:** Apply the attribute at the *struct level*, providing a comma-separated list of field definitions just like regular struct fields.
```rust
#[ derive( Former ) ]
#[ storage_fields( temp_count : i32, config_flag : Option< bool > ) ]
struct MyStruct
{
final_value : String,
}
```
* **Behavior:**
* The specified fields (e.g., `temp_count`, `config_flag`) are added to the `...FormerStorage` struct, wrapped in `Option` like regular fields.
* Setters *are* generated for these storage fields on the `...Former` struct (e.g., `.temp_count( value )`, `.config_flag( value )`).
* These fields are **not** included in the final struct (`MyStruct` in the example).
* Their values are typically accessed and used within a custom `Mutator` (using `#[ mutator( custom ) ]`) to influence the final values of the actual struct fields just before `.form()` completes.
**Example Snippet (Conceptual - See Full Example Linked Below):**
```rust
# #[ cfg( any( not( feature = "derive_former" ), not( feature = "enabled" ) ) ) ]
# fn main() {}
# #[ cfg( all( feature = "derive_former", feature = "enabled" ) ) ]
# fn main()
# {
use former::Former;
#[ derive( Debug, PartialEq, Former ) ]
#[ storage_fields( a : i32, b : Option< String > ) ] // Temporary fields
#[ mutator( custom ) ] // We need a mutator to use the storage fields
pub struct StructWithStorage
{
c : String, // Final field
}
// Custom mutator implementation needed to use storage fields 'a' and 'b'
impl< C, F > former::FormerMutator for StructWithStorageFormerDefinitionTypes< C, F >
{
#[ inline ]
fn form_mutation( storage : &mut Self::Storage, _context : &mut Option< Self::Context > )
{
// Use storage fields 'a' and 'b' to calculate final field 'c'
let val_a = storage.a.unwrap_or( 0 ); // Get value or default
let val_b = storage.b.as_deref().unwrap_or( "default_b" );
storage.c = Some( format!( "{} - {}", val_a, val_b ) ); // Set the *storage* for 'c'
}
}
let result = StructWithStorage::former()
.a( 13 ) // Set storage field 'a'
.b( "value_b".to_string() ) // Set storage field 'b'
// .c() is not called directly, it's set by the mutator
.form(); // Mutator runs, then final struct is built
assert_eq!( result.c, "13 - value_b" );
# }
```
[See full example code](https://github.com/Wandalen/wTools/blob/master/module/core/former/examples/former_custom_mutator.rs)
### Custom Mutators (`#[ mutator( custom ) ]` + `impl FormerMutator`)
For complex scenarios where the final field values depend on the combination of multiple inputs or require calculations just before the object is built, you can define a custom **mutator**.
* **Purpose:** To execute custom logic that modifies the `...FormerStorage` or `Context` immediately before the `FormingEnd::call` method finalizes the object.
* **Trigger:** Apply the `#[ mutator( custom ) ]` attribute to the struct definition. This tells `#[ derive( Former ) ]` *not* to generate the default (empty) `impl FormerMutator`.
* **Implementation:** You must manually implement the `former_types::FormerMutator` trait for the generated `...FormerDefinitionTypes` struct associated with your main struct.
```rust
impl< > former::FormerMutator
for YourStructFormerDefinitionTypes< >
{
fn form_mutation( storage : &mut Self::Storage, context : &mut Option< Self::Context > )
{
}
}
```
* **Execution:** The `form_mutation` method runs automatically when `.form()` or `.end()` is called, right before the `End` condition's `call` method executes.
* **Use Cases:**
* Implementing complex default logic based on other fields.
* Performing validation that requires access to multiple fields simultaneously.
* Calculating derived fields.
* Utilizing values from `#[ storage_fields( ... ) ]` to set final struct fields.
**Example Snippet (Conceptual - See Full Example Linked Below):**
(The example for `storage_fields` also demonstrates a custom mutator)
```rust
# #[ cfg( any( not( feature = "derive_former" ), not( feature = "enabled" ) ) ) ]
# fn main() {}
# #[ cfg( all( feature = "derive_former", feature = "enabled" ) ) ]
# fn main()
# {
use former::Former;
#[ derive( Debug, PartialEq, Former ) ]
#[ storage_fields( a : i32, b : Option< String > ) ]
#[ mutator( custom ) ] // Enable custom mutator
pub struct StructWithMutator
{
c : String,
}
// Provide the custom implementation
impl< C, F > former::FormerMutator for StructWithMutatorFormerDefinitionTypes< C, F >
{
#[ inline ]
fn form_mutation( storage : &mut Self::Storage, _context : &mut Option< Self::Context > )
{
// Logic using storage fields 'a' and 'b' to set storage for 'c'
let val_a = storage.a.unwrap_or( 0 );
let val_b = storage.b.as_deref().unwrap_or( "default_b" );
storage.c = Some( format!( "Mutated: {} - {}", val_a, val_b ) );
}
}
let result = StructWithMutator::former()
.a( 13 )
.b( "value_b".to_string() )
// .c() is not called; its value in storage is set by the mutator
.form(); // form_mutation runs before final construction
assert_eq!( result.c, "Mutated: 13 - value_b" );
# }
```
[See full example code](https://github.com/Wandalen/wTools/blob/master/module/core/former/examples/former_custom_mutator.rs)
### Custom Definitions & End Handlers
For the ultimate level of control over the forming process, you can define entirely custom `FormerDefinition` and `FormingEnd` implementations. This is typically needed for integrating non-standard collections or implementing highly specialized finalization logic.
* **Motivation:**
* Integrating custom collection types not supported by default.
* Changing the final `Formed` type returned by `.form()`/`.end()`.
* Implementing complex validation or transformation logic during finalization.
* Managing resources or side effects at the end of the building process.
* **Core Traits to Implement:**
1. **`former_types::FormerDefinitionTypes`:** Define your `Storage`, `Context`, and `Formed` types.
2. **`former_types::FormerMutator`:** Implement `form_mutation` if needed (often empty if logic is in `FormingEnd`).
3. **`former_types::FormerDefinition`:** Link your `Types` and specify your custom `End` type.
4. **`former_types::FormingEnd`:** Implement the `call` method containing your finalization logic. This method consumes the `Storage` and `Context` and must return the `Formed` type.
* **Usage:**
* You typically wouldn't use `#[ derive( Former ) ]` on the struct itself if you're providing a fully custom definition ecosystem.
* Instead, you manually define the `Former`, `Storage`, `DefinitionTypes`, `Definition`, and `End` structs/traits.
* The `CollectionFormer` or a manually defined `Former` struct is then used with your custom `Definition`.
**Example (Custom Definition to Sum Vec Elements):**
This example defines a custom former that collects `i32` values into a `Vec< i32 >` (as storage) but whose final `Formed` type is the `i32` sum of the elements.
```rust
# #[ cfg( not( all( feature = "enabled", feature = "derive_former", any( feature = "use_alloc", not( feature = "no_std" ) ) ) ) ) ]
# fn main() {}
# #[ cfg( all( feature = "enabled", feature = "derive_former", any( feature = "use_alloc", not( feature = "no_std" ) ) ) ) ]
# fn main()
# {
use former_types::*; // Import necessary traits
// 1. Define a marker struct for the custom definition
struct SummationDefinition;
// 2. Implement FormerDefinitionTypes
impl FormerDefinitionTypes for SummationDefinition
{
type Storage = Vec< i32 >; // Store numbers in a Vec
type Formed = i32; // Final result is the sum (i32)
type Context = (); // No context needed
}
// 3. Implement FormerMutator (empty in this case)
impl FormerMutator for SummationDefinition {}
// 4. Implement FormerDefinition, linking Types and End
impl FormerDefinition for SummationDefinition
{
type Types = SummationDefinition;
type End = SummationDefinition; // Use self as the End handler
type Storage = Vec< i32 >;
type Formed = i32;
type Context = ();
}
// 5. Implement FormingEnd for the End type (SummationDefinition itself)
impl FormingEnd< SummationDefinition > for SummationDefinition
{
fn call
(
&self,
storage : Vec< i32 >, // Consumes the storage (Vec)
_context : Option< () >
) -> i32 // Returns the Formed type (i32)
{
// Custom logic: sum the elements
storage.iter().sum()
}
}
// Use the custom definition with CollectionFormer
let sum = CollectionFormer::< i32, SummationDefinition >::new( SummationDefinition )
.add( 1 )
.add( 2 )
.add( 10 )
.form(); // Invokes SummationDefinition::call
assert_eq!( sum, 13 );
# }
```
[See full example code](https://github.com/Wandalen/wTools/blob/master/module/core/former/examples/former_custom_definition.rs)
### Custom Collections
While `former` provides built-in support for standard library collections when using `#[ subform_collection ]` or `#[ subform_entry ]`, you can integrate your own custom collection types by implementing the necessary `former_types::Collection` traits.
* **Motivation:** Allow the `former` derive macro's subform features (especially `#[ subform_collection ]` and `#[ subform_entry ]`) to work seamlessly with your custom data structures that behave like collections.
* **Core Traits to Implement for the Custom Collection Type:**
1. **`former_types::Collection`:**
* Define `type Entry` (the type added/iterated, e.g., `K` for a set, `(K, V)` for a map).
* Define `type Val` (the logical value type, e.g., `K` for a set, `V` for a map).
* Implement `fn entry_to_val( Self::Entry ) -> Self::Val`.
2. **`former_types::CollectionAdd`:**
* Implement `fn add( &mut self, Self::Entry ) -> bool`.
3. **`former_types::CollectionAssign`:**
* Implement `fn assign< Elements >( &mut self, Elements ) -> usize where Elements : IntoIterator< Item = Self::Entry >`.
* Requires `Self : IntoIterator< Item = Self::Entry >`.
4. **`former_types::CollectionValToEntry< Self::Val >`:**
* Define `type Entry` (same as `Collection::Entry`).
* Implement `fn val_to_entry( Self::Val ) -> Self::Entry`. This is crucial for `#[ subform_entry ]` to map a formed value back into an entry suitable for adding to the collection.
5. **`former_types::Storage` + `former_types::StoragePreform`:** Implement these to define how the collection itself is handled as storage (usually just returning `Self`).
6. **`Default`:** Your collection likely needs to implement `Default`.
7. **`IntoIterator`:** Required for `CollectionAssign`.
* **Custom Definition (Optional but Recommended):** While not strictly required if your collection mimics a standard one closely, providing a custom `FormerDefinition` (like `MyCollectionDefinition`) allows for more control and clarity, especially if using `#[ subform_collection( definition = MyCollectionDefinition ) ]`. You'd implement:
1. `MyCollectionDefinitionTypes` (implementing `FormerDefinitionTypes`).
2. `MyCollectionDefinition` (implementing `FormerDefinition`).
3. Implement `EntityTo...` traits (`EntityToFormer`, `EntityToStorage`, `EntityToDefinition`, `EntityToDefinitionTypes`) to link your custom collection type to its definition and former.
* **Usage with Derive:** Once the traits are implemented, you can use your custom collection type in a struct and apply `#[ subform_collection ]` or `#[ subform_entry ]` as usual. You might need `#[ subform_collection( definition = ... ) ]` if you created a custom definition.
**Example (Conceptual - See Full Example Linked Below):**
Imagine a `LoggingSet<T>` that wraps a `HashSet<T>` but logs additions.
```rust
# #[ cfg( not( all( feature = "enabled", feature = "derive_former", any( feature = "use_alloc", not( feature = "no_std" ) ) ) ) ) ]
# fn main() {}
# #[ cfg( all( feature = "enabled", feature = "derive_former", any( feature = "use_alloc", not( feature = "no_std" ) ) ) ) ]
# fn main() {
# use std::collections::HashSet;
# use former_types::*;
# #[ derive( Debug, PartialEq, Default ) ]
# pub struct LoggingSet< K > where K : core::cmp::Eq + core::hash::Hash, { set : HashSet< K > }
# impl< K : core::cmp::Eq + core::hash::Hash > Collection for LoggingSet< K > { type Entry = K; type Val = K; fn entry_to_val( e : K ) -> K { e } }
# impl< K : core::cmp::Eq + core::hash::Hash > CollectionAdd for LoggingSet< K > { fn add( &mut self, e : K ) -> bool { println!( "Adding: {:?}", e ); self.set.insert( e ) } }
# impl< K : core::cmp::Eq + core::hash::Hash > IntoIterator for LoggingSet< K > { type Item = K; type IntoIter = std::collections::hash_set::IntoIter<K>; fn into_iter( self ) -> Self::IntoIter { self.set.into_iter() } }
# impl< K : core::cmp::Eq + core::hash::Hash > CollectionAssign for LoggingSet< K > { fn assign< Elements : IntoIterator< Item = K > >( &mut self, elements : Elements ) -> usize { self.set.clear(); self.set.extend( elements ); self.set.len() } }
# impl< K : core::cmp::Eq + core::hash::Hash > CollectionValToEntry< K > for LoggingSet< K > { type Entry = K; fn val_to_entry( val : K ) -> K { val } }
# impl< K : core::cmp::Eq + core::hash::Hash > Storage for LoggingSet< K > { type Preformed = Self; }
# impl< K : core::cmp::Eq + core::hash::Hash > StoragePreform for LoggingSet< K > { fn preform( self ) -> Self { self } }
# #[ derive( former::Former, Debug, PartialEq, Default ) ]
# pub struct Config { #[ subform_collection ] items : LoggingSet< String > }
// Assume LoggingSet<T> implements all necessary Collection traits...
let config = Config::former()
.items() // Returns a CollectionFormer using LoggingSet's trait impls
.add( "item1".to_string() ) // Uses LoggingSet::add
.add( "item2".to_string() )
.end()
.form();
assert!( config.items.set.contains( "item1" ) );
assert!( config.items.set.contains( "item2" ) );
# }
```
[See full example code](https://github.com/Wandalen/wTools/blob/master/module/core/former/examples/former_custom_collection.rs)
## Attribute Reference
Customize the behavior of `#[ derive( Former ) ]` using the following attributes:
### Struct-Level Attributes
Apply these directly above the `struct` or `enum` definition.
* **`#[ storage_fields( field_name : FieldType, ... ) ]`**
* Defines extra fields exclusive to the temporary `...FormerStorage` struct. These fields won't be part of the final formed struct but can be set via the former and used for intermediate calculations, often within a custom `Mutator`.
* *Example:* `#[ storage_fields( counter : i32, is_valid : Option< bool > ) ]`
* **`#[ mutator( custom ) ]`**
* Disables the automatic generation of the default (empty) `impl former::FormerMutator`. You must provide your own implementation to define custom logic in the `form_mutation` method, which runs just before the `End` condition finalizes the struct.
* *Example:* `#[ mutator( custom ) ]`
* **`#[ perform( fn method_name<...> () -> OutputType ) ]`**
* Specifies a method *on the original struct* to be called by the former's `.perform()` method *after* the struct instance has been formed. The `.perform()` method will return the result of this specified method instead of the struct instance itself. The signature provided must match a method implemented on the struct.
* *Example:* `#[ perform( fn finalize_setup( self ) -> Result< Self, SetupError > ) ]`
* **`#[ debug ]`**
* Prints the code generated by the `Former` derive macro to the console during compilation. Useful for understanding the macro's output or debugging issues.
* *Example:* `#[ derive( Former ) ] #[ debug ] struct MyStruct { ... }`
* **`#[ standalone_constructors ]`**
* Generates top-level constructor functions for the struct or enum variants.
* For structs, generates `fn my_struct( ... )`. For enums, generates `fn my_variant( ... )` for each variant.
* Arguments and return type depend on `#[ arg_for_constructor ]` attributes on fields (see below and Option 2 logic in Readme).
* *Example:* `#[ derive( Former ) ] #[ standalone_constructors ] struct MyStruct { ... }`
### Field-Level / Variant-Level Attributes
Apply these directly above fields within a struct or fields within an enum variant.
**General Field Control:**
* **`#[ former( default = expression ) ]`**
* Provides a default value for the field if its setter is not called during the building process. The `expression` must evaluate to a value assignable to the field's type.
* *Example:* `#[ former( default = 10 ) ] count : i32;`, `#[ former( default = "guest".to_string() ) ] user : String;`
* **`#[ arg_for_constructor ]`**
* Marks a field as a required argument for the standalone constructor generated by `#[ standalone_constructors ]`.
* Affects the constructor's signature and return type (see Option 2 logic in Readme).
* Cannot be applied directly to enum variants, only to fields *within* variants.
* *Example:* `#[ arg_for_constructor ] field_a : i32;`
**Scalar Field Control:** (Applies to simple fields or variants marked `#[scalar]`)
* **`#[ scalar ]`** (Implicit for simple struct fields, required for tuple/unit enum variants to get a direct *associated method* constructor)
* Ensures a standard setter method (`.field_name( value )`) or a direct constructor (`Enum::variant_name( value )`) is generated.
* **Arguments:**
* `name = new_setter_name`: Renames the setter method (e.g., `#[ scalar( name = set_field ) ]`).
* `setter = bool`: Explicitly enables/disables setter generation (e.g., `#[ scalar( setter = false ) ]`). Default: `true`.
* `debug`: Prints a sketch of the generated scalar setter to the console during compilation.
**Subformer Field/Variant Control:** (For nested building)
* **`#[ subform_scalar ]`** (Applies to struct fields whose type derives `Former`, or single-field tuple enum variants whose type derives `Former`)
* Generates a method returning a subformer for the nested struct/type (e.g., `.field_name()` returns `InnerFormer`). Default behavior for single-field enum variants holding a `Former`-derived type unless `#[scalar]` is used.
* **Arguments:**
* `name = new_setter_name`: Renames the subformer starter method (e.g., `#[ subform_scalar( name = configure_child ) ]`).
* `setter = bool`: Enables/disables the subformer starter method. Default: `true`.
* `debug`: Prints a sketch of the generated subform scalar setter and `End` struct to the console.
* **`#[ subform_collection ]`** (Applies to struct fields holding standard or custom collections)
* Generates a method returning a collection-specific subformer (e.g., `.field_name()` returns `VectorFormer` or `HashMapFormer`).
* **Arguments:**
* `definition = path::to::CollectionDefinition`: Specifies the collection type definition (e.g., `#[ subform_collection( definition = former::VectorDefinition ) ]`). Often inferred for standard collections. Required for custom collections unless `EntityToDefinition` is implemented.
* `name = new_setter_name`: Renames the subformer starter method (e.g., `#[ subform_collection( name = add_entries ) ]`).
* `setter = bool`: Enables/disables the subformer starter method. Default: `true`.
* `debug`: Prints a sketch of the generated subform collection setter and `End` struct.
* **`#[ subform_entry ]`** (Applies to struct fields holding collections where entries derive `Former`)
* Generates a method returning a subformer for a *single entry* of the collection (e.g., `.field_name()` returns `EntryFormer`). Requires `ValToEntry` for map types.
* **Arguments:**
* `name = new_setter_name`: Renames the entry subformer starter method (e.g., `#[ subform_entry( name = command ) ]`).
* `setter = bool`: Enables/disables the entry subformer starter method. Default: `true`.
* `debug`: Prints a sketch of the generated subform entry setter and `End` struct.
## Component Model Derives (Related Utilities)
While the core of this crate is the `#[ derive( Former ) ]` macro, the `former` crate (by re-exporting from `former_types` and `former_meta`) also provides a suite of related derive macros focused on **type-based component access and manipulation**. These are often useful in conjunction with or independently of the main `Former` derive.
These derives require the corresponding features to be enabled (they are enabled by default).
* **`#[ derive( Assign ) ]`:**
* Implements the `component_model_types::Assign< FieldType, IntoT >` trait for each field of the struct.
* Allows setting a field based on its **type**, using `.assign( value )` where `value` can be converted into the field's type.
* Requires fields to have unique types within the struct.
* *Example:* `my_struct.assign( 10_i32 ); my_struct.assign( "hello".to_string() );`
* **`#[ derive( ComponentFrom ) ]`:**
* Implements `std::convert::From< &YourStruct >` for each field's type.
* Allows extracting a field's value based on its **type** using `.into()` or `From::from()`.
* Requires fields to have unique types within the struct.
* *Example:* `let name : String = ( &my_struct ).into();`
* **`#[ derive( ComponentsAssign ) ]`:**
* Generates a helper trait (e.g., `YourStructComponentsAssign`) with a method (e.g., `.your_struct_assign( &other_struct )`).
* This method assigns values from fields in `other_struct` to fields of the *same type* in `self`.
* Requires `From< &OtherStruct >` to be implemented for each relevant field type.
* Useful for updating a struct from another struct containing a subset or superset of its fields.
* *Example:* `my_struct.your_struct_assign( &source_struct );`
* **`#[ derive( FromComponents ) ]`:**
* Implements `std::convert::From< T >` for the struct itself, where `T` is some source type.
* Allows constructing the struct *from* a source type `T`, provided `T` implements `Into< FieldType >` for each field in the struct.
* Requires fields to have unique types within the struct.
* *Example:* `let my_struct : YourStruct = source_struct.into();`
These component derives offer a powerful, type-driven way to handle data mapping and transformation between different struct types. Refer to the specific examples and `former_types` documentation for more details.
[See ComponentFrom example](https://github.com/Wandalen/wTools/blob/master/module/core/former/examples/former_component_from.rs)