1#[macro_export]
2macro_rules! default {
3 ( $name:ident { } ) => { $name::default() };
4 ( $name:ident { $field_name:tt : $value:tt $($tail:tt)* } ) => {
5 default!(@x $name { $field_name : } {$value} $($tail)* )
6 };
7 ( $name:expr ) => { $name };
8 ( @x $name:ident {$($processed:tt)*} {$($current:tt)+} $(,)? ) => {
9 $name{ $($processed)* default!($($current)+) , ..$name::default()}
10 };
11 ( @x $name:ident {$($processed:tt)+} {$($current:tt)+} , $field_name:tt : $value:tt $($tail:tt)* ) => {
12 default!(@x $name {$($processed)+ default!($($current)+), $field_name :} {$value} $($tail)*)
13 };
14 ( @x $name:ident {$($processed:tt)+} {$($current:tt)+} $value:tt $($tail:tt)*) => {
15 default!( @x $name {$($processed)+} {$($current)+ $value} $($tail)* )
16 };
17}
18
19#[cfg(test)]
20mod tests {
21 #[derive(Default, Debug)]
22 struct Foo {
23 a: i32,
24 b: f64,
25 c: Bar,
26 }
27 #[derive(Default, Debug)]
28 struct Bar {
29 d: i32,
30 e: i32,
31 }
32
33 #[test]
34 fn it_works() {
35 check(default!(Foo {}), Foo::default());
36 check(
37 default!(Foo { a: 1 }),
38 Foo {
39 a: 1,
40 ..Foo::default()
41 },
42 );
43 check(
44 default!(Foo { a: 1, b: 1.0 }),
45 Foo {
46 a: 1,
47 b: 1.0,
48 ..Foo::default()
49 },
50 );
51
52 check(
53 default!(Foo { a: 1 + 2, b: 1.0 }),
54 Foo {
55 a: 3,
56 b: 1.0,
57 ..Foo::default()
58 },
59 );
60 check(
61 default!(Foo { c: Bar { d: 1 } }),
62 Foo {
63 c: Bar {
64 d: 1,
65 ..Bar::default()
66 },
67 ..Foo::default()
68 },
69 );
70 }
71 fn check(foo1: Foo, foo2: Foo) {
72 assert_eq!(format!("{:?}", foo1), format!("{:?}", foo2));
73 }
74}