Expand description
§Module :: variadic_from
The variadic_from crate provides a powerful procedural macro and helper traits to simplify the creation of flexible constructors for Rust structs. It automates the implementation of From-like traits, allowing structs to be instantiated from a variable number of arguments or tuples, reducing boilerplate and enhancing code readability.
§Features
- Variadic Constructors: Easily create instances of structs from 0 to 3 arguments using the
from!macro. - Derive Macro (
VariadicFrom): Automatically implementsFromNtraits and standardFrom<T>/From<tuple>for structs with 1, 2, or 3 fields. - Tuple Conversion: Seamlessly convert tuples into struct instances using the standard
FromandIntotraits. - Compile-time Safety: The
from!macro provides compile-time errors for invalid argument counts (e.g., more than 3 arguments). - No Code Generation for >3 Fields: The derive macro intelligently generates no code for structs with 0 or more than 3 fields, preventing unexpected behavior.
§Quick Start
To get started with variadic_from, follow these simple steps:
-
Add to your
Cargo.toml:[dependencies] variadic_from = "0.1" # Or the latest version variadic_from_meta = { path = "../variadic_from_meta" } # If using from workspace -
Basic Usage Example:
This example demonstrates the use of the
variadic_frommacro to implement flexible constructors for a struct, allowing it to be instantiated from different numbers of arguments or tuples. It also showcases how to derive common traits likeDebug,PartialEq,Default, andVariadicFromfor the struct.#[test] fn readme_example_basic() { use variadic_from::exposed::*; #[ derive( Debug, PartialEq, Default, VariadicFrom ) ] struct MyStruct { a : i32, b : i32, } let got : MyStruct = from!(); let exp = MyStruct { a : 0, b : 0 }; assert_eq!( got, exp ); let got : MyStruct = from!( 13 ); let exp = MyStruct { a : 13, b : 13 }; assert_eq!( got, exp ); let got : MyStruct = from!( 13, 14 ); let exp = MyStruct { a : 13, b : 14 }; assert_eq!( got, exp ); } -
Expanded Code Example (What the macro generates):
This section shows the code that the
VariadicFromderive macro generates forMyStruct(a two-field struct), including theFrom2trait implementation and the standardFrom<(T1, T2)>implementation.#[test] fn readme_example_expanded() { use variadic_from::exposed::*; #[ derive( Debug, PartialEq, Default ) ] struct MyStruct { a : i32, b : i32, } impl From2< i32, i32 > for MyStruct { fn from2( a : i32, b : i32 ) -> Self { Self{ a : a, b : b } } } impl From< ( i32, i32 ) > for MyStruct { #[ inline( always ) ] fn from( ( a, b ) : ( i32, i32 ) ) -> Self { Self::from2( a, b ) } } let got : MyStruct = from!(); let exp = MyStruct { a : 0, b : 0 }; assert_eq!( got, exp ); let got : MyStruct = from!( 13 ); let exp = MyStruct { a : 13, b : 13 }; assert_eq!( got, exp ); let got : MyStruct = from!( 13, 14 ); let exp = MyStruct { a : 13, b : 14 }; assert_eq!( got, exp ); }
§Macro Behavior Details
-
#[derive(VariadicFrom)]:- For a struct with 1 field (e.g.,
struct MyStruct(i32)orstruct MyStruct { field: i32 }), it generates:impl From1<FieldType> for MyStructimpl From<FieldType> for MyStruct(delegating toFrom1)
- For a struct with 2 fields (e.g.,
struct MyStruct(i32, i32)orstruct MyStruct { a: i32, b: i32 }), it generates:impl From2<Field1Type, Field2Type> for MyStructimpl From<(Field1Type, Field2Type)> for MyStruct(delegating toFrom2)- Additionally, it generates
impl From1<Field1Type> for MyStruct(whereField1Typeis used for all fields, for convenience).
- For a struct with 3 fields, similar
From3andFrom<(T1, T2, T3)>implementations are generated, along withFrom1andFrom2convenience implementations. - For structs with 0 fields or more than 3 fields, the derive macro generates no code. This means you cannot use
from!orFromNtraits with such structs unless you implement them manually.
- For a struct with 1 field (e.g.,
-
from!Macro:from!()->Default::default()from!(arg1)->From1::from1(arg1)from!(arg1, arg2)->From2::from2(arg1, arg2)from!(arg1, arg2, arg3)->From3::from3(arg1, arg2, arg3)from!(...)with more than 3 arguments will result in a compile-time error.
§API Documentation
For detailed API documentation, visit docs.rs/variadic_from.
§Contributing
We welcome contributions! Please see our CONTRIBUTING.md for guidelines on how to contribute.
§License
This project is licensed under the License file.
§Troubleshooting
Too many argumentscompile error withfrom!macro: This means you are trying to usefrom!with more than 3 arguments. The macro currently only supports up to 3 arguments. Consider using a regular struct constructor or manually implementingFromNfor more fields.FromNtrait not implemented: Ensure your struct has#[derive(VariadicFrom)]and the number of fields is between 1 and 3 (inclusive). If it’s a 0-field or >3-field struct, the derive macro will not generateFromNimplementations.- Conflicting
Fromimplementations: If you manually implementFrom<T>orFrom<(T1, ...)>for a struct that also derivesVariadicFrom, you might encounter conflicts. Prefer using the derive macro for automatic implementations, or manually implementFromNtraits and use thefrom!macro.
§Project Structure
The variadic_from project consists of two main crates:
variadic_from: The main library crate, containing theFromNtraits, thefrom!declarative macro, and blanket implementations.variadic_from_meta: A procedural macro crate that implements the#[derive(VariadicFrom)]macro.
§Testing
To run all tests for the project, including unit tests, integration tests, and doc tests:
cargo test --workspaceTo run tests for a specific crate:
cargo test -p variadic_from --all-targets
cargo test -p variadic_from_meta --all-targetsTo run only the doc tests:
cargo test -p variadic_from --doc§Debugging
For debugging procedural macros, you can use cargo expand to see the code generated by the macro. Add #[debug] attribute to your struct to see the expanded code.
cargo expand --example variadic_from_trivialYou can also use a debugger attached to your test runner.
# Example for VS Code with CodeLLDB
# In .vscode/launch.json:
# {
# "type": "lldb",
# "request": "launch",
# "name": "Debug variadic_from_tests",
# "cargo": {
# "args": [
# "test",
# "--package=variadic_from",
# "--test=variadic_from_tests",
# "--no-run",
# "--message-format=json-render-diagnostics"
# ],
# "filter": {
# "name": "variadic_from_tests",
# "kind": "test"
# }
# },
# "args": [],
# "cwd": "${workspaceFolder}"
# }§Try out from the repository
git clone https://github.com/Wandalen/wTools
cd wTools/module/core/variadic_from # Navigate to the crate directory
cargo run --example variadic_from_trivialRe-exports§
pub use ::variadic_from_meta::VariadicFrom;
Modules§
- dependency
- Namespace with dependencies.
- exposed
- Exposed namespace of the module.
- orphan
- Orphan namespace of the module.
- own
- Own namespace of the module.
- prelude
- Prelude to use essentials:
use my_module ::prelude :: *. - variadic
- Internal implementation of variadic
Fromtraits and macro.
Macros§
- from
- Macro to construct a struct from variadic arguments.
Traits§
- From1
- Trait for converting from one argument.
- From2
- Trait for converting from two arguments.
- From3
- Trait for converting from three arguments.
Derive Macros§
- Variadic
From - Derive macro for
VariadicFrom.