Crate autodefault[−][src]
Has this ever happened to you?
#[derive(Debug, Default, PartialEq, Eq)] struct Inner { x: i32, y: i32, z: i32, } #[derive(Debug, Default, PartialEq, Eq)] struct Mid { a: Inner, b: Inner, c: Inner, d: Inner } #[derive(Debug, Default, PartialEq, Eq)] struct Outer { mid1: Mid, mid2: Mid, mid3: Mid, mid4: Mid, } fn build_outer() -> Outer { Outer { mid1: Mid { a: Inner { x: 10, ..Default::default() // :D }, b: Inner { y: 10, ..Default::default() // :) }, ..Default::default() // :| }, mid2: Mid { b: Inner { z: 10, ..Default::default() // :/ }, ..Default::default() // :( }, ..Default::default() // >:( } }
Wouldn’t it be nice if you could omit all the tedious ..Default::default()
calls when building deeply nested struct literals? Now you can! With
autodefault
, it’s never been easier to build up a large struct expression
for your tests, bevy components, or anything else
you might need!. Simply tag any function with the #[autodefault]
attribute
and let us handle the rest:
use autodefault::autodefault; #[autodefault] fn build_outer_simple() -> Outer { Outer { mid1: Mid { a: Inner { x: 10 }, b: Inner { y: 10 }, }, mid2: Mid { b: Inner { z: 10 }, } } } // :O assert_eq!(build_outer(), build_outer_simple())
It’s never been easier!
What it’s actually doing
When applied to a function, the #[autodefault]
will scan the body of the
function for all struct expressions that don’t already have a ..rest
trailing
initializer and insert a ..Default::default()
. It will do this unconditionally
for all struct expressions, regardless of whether they actually implement
Default
, so be sure to refactor into helper functions as necessary:
use autodefault::autodefault; struct NoDefault { x: i32, y: i32, z: i32, } #[autodefault] fn nope() { let _nope = NoDefault { x: 10 }; }
Filtering Default
insertions
If you only want to add ..Default::default()
to some of the structs in your
function, autodefault
supports filtering by type name:
use autodefault::autodefault; #[derive(Default)] struct HasDefault { a: i32, b: i32, c: i32, d: i32, } struct NoDefault1 { a: HasDefault, } struct NoDefault2 { a: NoDefault1, } #[autodefault(except(NoDefault1, NoDefault2))] fn example1() { let _data = NoDefault2 { a: NoDefault1 { a: HasDefault {} } }; } #[autodefault(only(HasDefault))] fn example2() { let _data = NoDefault2 { a: NoDefault1 { a: HasDefault {} } }; }
Other behaviors
autodefault
will not descend into nested item definitions; if you nest an
fn
item inside another fn
, you’ll need to tag the inner function with
autodefault
again.
use autodefault::autodefault; #[derive(Default)] struct HasDefault { x: i32 } struct NoDefault { x: i32 } #[autodefault] fn outer() { let _x = HasDefault {}; fn inner() { let _x = NoDefault {x: 10}; } }
Attribute Macros
autodefault | Modify a function such that some or all struct expressions include
|