Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 107 additions & 0 deletions module/core/former/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,113 @@ Where `former` significantly simplifies complex scenarios is in building collect

`former` provides different subform attributes (`#[ subform_collection ]`, `#[ subform_entry ]`, `#[ subform_scalar ]`) for various collection and nesting patterns.

## Standalone Constructors

For scenarios where you want a direct constructor function instead of always starting with `YourType::former()`, `former` offers standalone constructors.

* **Enable:** Add `#[ standalone_constructors ]` to your struct or enum definition.
* **Function Name:** A function named after your type (in snake_case) will be generated (e.g., `my_struct()` for `struct MyStruct`). For enums, functions are named after variants (e.g., `my_variant()` for `enum E { MyVariant }`).
* **Arguments:** By default, the constructor takes no arguments and returns the `Former` type.
* **Specify Arguments:** Mark specific fields with `#[ arg_for_constructor ]` to make them required arguments for the standalone constructor.
* **Return Type (Option 2 Logic):**
* If **all** fields of the struct/variant are marked with `#[ arg_for_constructor ]`, the standalone constructor returns the instance directly (`Self`).
* If **zero or some** fields are marked, the standalone constructor returns the `Former` type, pre-initialized with the provided arguments.

**Example: Struct Standalone Constructors**

```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 ) ]
#[ standalone_constructors ] // Enable standalone constructors
pub struct ServerConfig
{
#[ arg_for_constructor ] // This field is a constructor arg
host : String,
#[ arg_for_constructor ] // This field is also a constructor arg
port : u16,
timeout : Option< u32 >, // This field is NOT a constructor arg
}

// Not all fields are args, so `server_config` returns the Former
let config_former = server_config( "localhost".to_string(), 8080u16 ); // Added u16 suffix

// Set the remaining field and form
let config = config_former
.timeout( 5000u32 ) // Added u32 suffix
.form();

assert_eq!( config.host, "localhost" );
assert_eq!( config.port, 8080u16 ); // Added u16 suffix
assert_eq!( config.timeout, Some( 5000u32 ) ); // Added u32 suffix

#[ derive( Debug, PartialEq, Former ) ]
#[ standalone_constructors ]
pub struct Point
{
#[ arg_for_constructor ]
x : i32,
#[ arg_for_constructor ]
y : i32,
}

// ALL fields are args, so `point` returns Self directly
let p = point( 10, 20 );
assert_eq!( p.x, 10 );
assert_eq!( p.y, 20 );
# }
```

**Example: Enum Standalone Constructors**

```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 ) ]
#[ standalone_constructors ]
pub enum Message
{
Quit, // Unit variant constructor `quit()` returns Self
Write // Tuple variant constructor `write()` returns Former
{
#[ arg_for_constructor ] // Only this field is an arg
text : String,
urgent : bool, // Not an arg
},
Move // Struct variant constructor `move_point()` returns Self
{
#[ arg_for_constructor ]
x : i32,
#[ arg_for_constructor ]
y : i32,
}
}

// Unit variant - returns Self
let m1 = quit();
assert_eq!( m1, Message::Quit );

// Tuple variant - not all fields are args, returns Former
let m2_former = write( "hello".to_string() );
let m2 = m2_former.urgent( true ).form();
assert_eq!( m2, Message::Write { text: "hello".to_string(), urgent: true } );

// Struct variant - all fields are args, returns Self
let m3 = r#move( 1, 2 ); // Use raw identifier `r#move` as `move` is a keyword
assert_eq!( m3, Message::Move { x: 1, y: 2 } );
# }
```

## Key Features Overview

* **Automatic Builder Generation:** `#[ derive( Former ) ]` for structs and enums.
Expand Down
16 changes: 14 additions & 2 deletions module/core/former/advanced.md
Original file line number Diff line number Diff line change
Expand Up @@ -814,19 +814,31 @@ Apply these directly above the `struct` or `enum` definition.
* 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 variants within an enum.
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 constructor)
* **`#[ 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 ) ]`).
Expand Down
Loading
Loading