1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
//! Substruct is a proc-macro to allow you to easily declare structs which are
//! subsets of another struct. It automatically creates conversion methods
//! between the parent and child structs and will propagate any derives and
//! attributes to the child struct.
//!
//! A basic use of substruct looks like this
//! ```
//! use substruct::substruct;
//!
//! #[substruct(SubQuery)]
//! #[derive(Clone, Debug, Eq, PartialEq)]
//! pub struct Query {
//! #[substruct(SubQuery)]
//! pub a: &'static str,
//! pub b: usize
//! }
//!
//! let subquery = SubQuery { a: "query" };
//! let query = Query { a: "query", b: 5 };
//!
//! assert_eq!(subquery.into_query(5), query);
//! ```
//!
//! and that will expand to produce
//! ```
//! #[derive(Clone, Debug, Eq, PartialEq)]
//! pub struct Query {
//! pub a: &'static str,
//! pub b: usize
//! }
//!
//! #[derive(Clone, Debug, Eq, PartialEq)]
//! pub struct SubQuery {
//! pub a: &'static str,
//! }
//! ```
//!
//! Substruct isn't just limited to creating a single child struct, you can use
//! it to create many at once:
//!
//! ```
//! # use substruct::substruct;
//! #[substruct(Vec2, Vec3)]
//! pub struct Vec4<T> {
//! #[substruct(Vec2, Vec3)]
//! pub x: T,
//!
//! #[substruct(Vec2, Vec3)]
//! pub y: T,
//!
//! #[substruct(Vec3)]
//! pub z: T,
//!
//! pub w: T,
//! }
//! ```
//!
//! **It is important that the `#[substruct]` attribute is placed before other
//! attributes.** The `#[substruct]` attribute macro can only see attributes
//! that come after it, with the exception of doc comments, so any attributes
//! that are evaluated before it will not be duplicated. While you can use this
//! for attributes that should only be included in the parent struct, it is
//! clearer if you use the `#[substruct_attr]` attribute macro documented below.
//!
//!
//! # Overriding documentation for emitted structs and fields
//! Sometimes you may want to override the emitted documentation for a struct
//! or field. To do so, document the struct identifier within the `#[substruct]`
//! parameters:
//!
//! ```
//! # use substruct::substruct;
//! #
//! /// All the parameters.
//! #[substruct(
//! /// A smaller set of parameters.
//! FilteredParams
//! )]
//! #[derive(Clone, Debug)]
//! pub struct Params {
//! #[substruct(FilteredParams)]
//! pub limit: bool,
//! pub filter: String,
//! }
//! ```
//!
//! For consistency, you can also specify the docs for the parent struct within
//! the `#[substruct]` attribute:
//!
//! ```
//! # use substruct::substruct;
//! #[substruct(
//! /// The big kahuna.
//! BigKahuna,
//!
//! /// The not-so-big kahuna.
//! SmallKahuna
//! )]
//! #[derive(Clone, Debug)]
//! pub struct BigKahuna {
//! pub name: String,
//!
//! #[substruct(SmallKahuna)]
//! pub profession: String,
//! }
//! ```
//!
//! # Overriding visibility for emitted structs and fields
//! Normally, `substruct` will copy the visibility definition over from the
//! base struct. However, you can override it by adding a visibility specifier
//! in front of the struct name within the `#[substruct]` attribute.
//! ```
//! # use substruct::substruct;
//! #
//! // Both A and B are pub, but C is pub(crate).
//! #[substruct(B, pub(crate) C)]
//! pub struct A {
//! // This field is public in structs A and C, but only pub(crate) in C.
//! #[substruct(pub(crate) B, C)]
//! pub field1: u32,
//!
//! // Making a field private can be done by using pub(self)
//! #[substruct(pub(self) C)]
//! pub field2: u32,
//!
//! // You can also override the visibility when using expressions.
//! // The overridden visibility applies to all structs specified in the
//! // expression.
//! #[substruct(pub(crate) any(B, C))]
//! pub field3: u32,
//! }
//! ```
//!
//! # Managing attributes on generated structs
//! Sometimes you may want attributes to only apply to some of the emitted
//! structs. To do so, you can use the `#[substruct_attr]` macro to only emit
//! these attributes on the desired structs:
//! ```
//! # use substruct::substruct;
//! # use serde::{Serialize, Deserialize};
//! #
//! #[substruct(ThingB, ThingC, ThingD)]
//! #[derive(Serialize, Deserialize)]
//! pub struct ThingA {
//! // This field is present in ThingA, ThingB, and ThingC but only has the
//! // serde rename attribute in ThingB.
//! #[substruct(ThingB, ThingC)]
//! #[substruct_attr(ThingB, serde(rename = "a2"))]
//! pub a: String,
//!
//! // You can also use the parent struct as a filter.
//! #[substruct(ThingD, ThingC)]
//! #[substruct_attr(ThingA, serde(alias = "d"))]
//! pub b: usize,
//! }
//! ```
//!
//! For more complicated use cases `#[substruct_attr]` supports a similar
//! expression language to the `#[cfg]` macro.
//!
//! ```
//! # use substruct::substruct;
//! # use serde::{Serialize, Deserialize};
//! #
//! #[substruct(A, B, C, D, E, F)]
//! #[derive(Clone, Debug, Serialize, Deserialize)]
//! pub struct A {
//! // This field is available on all structs except and the serde
//! // attribute is available on all structs except D (and B).
//! #[substruct(not(B))]
//! #[substruct_attr(not(D), serde(alias = "f2"))]
//! pub f1: u32,
//! }
//! ```
//!
//! The expressions you can use here are
//! - `<ident>` - true when emitting a struct with the same name
//! - `not(<expr>)` - true if the inner expression is false
//! - `any(<expr>...)` - true if _any_ of the inner expressions are true
//! - `all(<expr>...)` - true if _all_ of the inner expressions are true
//!
//! On struct fields, the `#[substruct]` entries are implicitly wrapped in an
//! `any` expression so you can do:
//!
//! ```
//! # use substruct::substruct;
//! #[substruct(A, B, C, D, E, F)]
//! pub struct A {
//! // This field is available on A, B, C, and D
//! #[substruct(any(B, C), D)]
//! pub f1: u32,
//! }
//! ```
//!
//! > The parent struct is always implicitly included in the set of structs
//! > that each field is emitted for. This means that putting `not(A)` in the
//! > the struct above would not exclude the field from `A` (and is, in fact,
//! > equivalent to `all()`).
//!
//! On its own, this isn't too useful, but where it does become useful is when
//! combined with documentation comment overrides.
//!
//! ```
//! # use substruct::substruct;
//! #[substruct(A, B, C, D, E, F)]
//! pub struct A {
//! /// This is the default documentation.
//! #[substruct(
//! /// This is the documentation on C, D, and F
//! any(C, D, F),
//!
//! /// And this is the documentation on B
//! B
//! )]
//! pub f1: u32,
//! }
//! ```
//!
//! If multiple overrides apply to a single field, then the first one to apply
//! will be used.
//!
//! # Generics
//! Generics are currently _mostly_ supported. You can use generics with
//! `#[substruct]` and the macro will expand them just fine:
//! ```
//! # use substruct::substruct;
//! #[substruct(SmallGeneric)]
//! pub struct Generic<'a, T> {
//! pub len: usize,
//!
//! #[substruct(SmallGeneric)]
//! pub value: &'a T,
//! }
//! ```
//!
//! However, if one of the child structs doesn't include a field that uses the
//! generic parameter or lifetime then that will result in an error
//! ```compile_fail
//! #[substruct(NoLifetime)]
//! pub struct UsesLifetime<'a> {
//! // ^^ error: lifetime not used in NoLifetime
//! #[substruct(NoLifetime)]
//! pub name: String,
//! pub text: &'a str,
//! }
//! ```
use TokenStream;
/// `#[substruct]` attribute macro.
///
/// See the [crate docs](crate) for detailed docs.