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 implementsFromN
traits and standardFrom<T>
/From<tuple>
for structs with 1, 2, or 3 fields. - Tuple Conversion: Seamlessly convert tuples into struct instances using the standard
From
andInto
traits. - 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_from
macro 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
, andVariadicFrom
for 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
VariadicFrom
derive macro generates forMyStruct
(a two-field struct), including theFrom2
trait 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 MyStruct
impl 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 MyStruct
impl From<(Field1Type, Field2Type)> for MyStruct
(delegating toFrom2
)- Additionally, it generates
impl From1<Field1Type> for MyStruct
(whereField1Type
is used for all fields, for convenience).
- For a struct with 3 fields, similar
From3
andFrom<(T1, T2, T3)>
implementations are generated, along withFrom1
andFrom2
convenience implementations. - For structs with 0 fields or more than 3 fields, the derive macro generates no code. This means you cannot use
from!
orFromN
traits 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 arguments
compile 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 implementingFromN
for more fields.FromN
trait 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 generateFromN
implementations.- Conflicting
From
implementations: 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 implementFromN
traits and use thefrom!
macro.
§Project Structure
The variadic_from
project consists of two main crates:
variadic_from
: The main library crate, containing theFromN
traits, 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 --workspace
To run tests for a specific crate:
cargo test -p variadic_from --all-targets
cargo test -p variadic_from_meta --all-targets
To 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_trivial
You 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_trivial
Re-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
From
traits 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
.