1#![doc = include_str!("../README.md")]
2
3#[macro_export]
4macro_rules! nested_struct {
5 (
7 $(#[$meta:meta])*
8 $vis:vis struct $name:ident {
9 $(
10 $(#[$field_meta:meta])*
11 $(@nested(#[$field_nested_meta:meta]))*
12 $field_vis:vis $field_name:ident : $field_ty:ident $({
13 $($field_ty_inner:tt)*
14 })?
15 ),*
16 $(,)? }
17 ) => {
18 $(#[$meta])* $vis struct $name {
20 $(
21 $(#[$field_meta])*
22 $field_vis $field_name : $field_ty
23 ),*
24 }
25
26 $(nested_struct! {
28 @nested
29 $(#[$field_nested_meta])*
30 $field_vis $field_ty $({
31 $($field_ty_inner)*
32 })?
33 })*
34 };
35
36 (@nested $(#[$meta:meta])* $vis:vis $name:ident {$($fields:tt)*}) => {
38 nested_struct! {
39 $(#[$meta])*
40 $vis struct $name {
41 $($fields)*
42 }
43 }
44 };
45
46 (@nested $(#[$meta:meta])* $vis:vis $name:ident) => {};
48
49 }
54
55#[cfg(test)]
56mod tests {
57 use super::*;
58
59 #[test]
60 fn supports_empty_named_struct() {
61 nested_struct! {
62 struct TestStruct {}
63 }
64
65 let _ = TestStruct {};
66 }
67
68 #[test]
69 #[allow(dead_code)]
70 fn supports_named_struct_with_regular_fields() {
71 nested_struct! {
72 struct TestStruct {
73 field: u32
74 }
75 }
76
77 let _ = TestStruct { field: 123 };
78 }
79
80 #[test]
81 #[allow(dead_code)]
82 fn supports_named_struct_with_nested_fields() {
83 nested_struct! {
84 struct TestStruct {
85 field: NestedField {
86 field: u32
87 }
88 }
89 }
90
91 let _ = TestStruct {
92 field: NestedField { field: 123 },
93 };
94 }
95
96 #[test]
97 #[allow(dead_code)]
98 fn supports_named_struct_with_deeply_nested_fields() {
99 nested_struct! {
100 struct TestStruct {
101 field: NestedField {
102 field: NestedField2 { field: u32 }
103 }
104 }
105 }
106
107 let _ = TestStruct {
108 field: NestedField {
109 field: NestedField2 { field: 123 },
110 },
111 };
112 }
113
114 #[test]
115 #[allow(dead_code)]
116 fn supports_named_struct_with_nested_fields_using_nested_attribute() {
117 {
119 nested_struct! {
120 #[derive(Clone)]
121 struct TestStruct {
122 @nested(#[derive(Clone)])
123 field: NestedField {
124 field: u32
125 }
126 }
127 }
128
129 let _ = TestStruct {
130 field: NestedField { field: 123 },
131 };
132 }
133
134 {
136 nested_struct! {
137 #[derive(Clone)]
138 struct TestStruct {
139 @nested(#[derive(Clone)])
140 field: NestedField {
141 @nested(#[derive(Clone)])
142 field: NestedField2 {
143 field: u32
144 }
145 }
146 }
147 }
148
149 let _ = TestStruct {
150 field: NestedField {
151 field: NestedField2 { field: 123 },
152 },
153 };
154 }
155 }
156}