@@ -8,50 +8,95 @@ mod attrs;
8
8
mod codegen;
9
9
mod consts;
10
10
11
- /// This macro enables generating versioned structs.
11
+ /// This macro enables generating versioned structs and enums .
12
12
///
13
- /// ## Usage Guide
13
+ /// # Usage Guide
14
14
///
15
- /// ### Quickstart
15
+ /// In this guide, code blocks usually come in pairs. The first code block
16
+ /// describes how the macro is used. The second expandable block displays the
17
+ /// generated piece of code for explanation purposes. It should be noted, that
18
+ /// the exact code can diverge from what is being depicted in this guide. For
19
+ /// example, `#[automatically_derived]` and `#[allow(deprecated)]` are removed
20
+ /// in most examples to reduce visual clutter.
21
+ ///
22
+ /// ## Declaring Versions
23
+ ///
24
+ /// It is **important** to note that this macro must be placed before any other
25
+ /// (derive) macros and attributes. This ensures that the macros and attributes
26
+ /// are applied to the generated versioned instances of the struct or enum.
27
+ ///
28
+ /// Before any of the fields or variants can be versioned, versions need to be
29
+ /// declared at the container level. Each version currently supports two
30
+ /// parameters: `name` and the `deprecated` flag. The `name` must be a valid
31
+ /// (and supported) format - currently, only Kubernetes API versions are
32
+ /// supported. The macro checks each declared version and reports any error
33
+ /// encountered during parsing.
16
34
///
17
35
/// ```
18
36
/// # use stackable_versioned_macros::versioned;
19
- /// #[versioned(
20
- /// version(name = "v1alpha1"),
21
- /// version(name = "v1beta1"),
22
- /// version(name = "v1"),
23
- /// version(name = "v2"),
24
- /// version(name = "v3")
25
- /// )]
37
+ /// #[versioned(version(name = "v1alpha1"))]
26
38
/// struct Foo {
27
- /// /// My docs
28
- /// #[versioned(
29
- /// added(since = "v1beta1"),
30
- /// changed(since = "v1", from_name = "gau"),
31
- /// deprecated(since = "v2", note = "not empty")
32
- /// )]
33
- /// deprecated_bar: usize,
34
- /// baz: bool,
39
+ /// bar: usize,
35
40
/// }
36
41
/// ```
37
42
///
38
- /// ### Declaring Versions
43
+ /// <details>
44
+ /// <summary>Generated code</summary>
45
+ ///
46
+ /// 1. The `#[automatically_derived]` attribute indicates that the following
47
+ /// piece of code is automatically generated by a macro instead of being
48
+ /// handwritten by a developer. This information is used by cargo and rustc.
49
+ /// 2. For each declared version, a new module containing the struct or enum
50
+ /// (container) is generated. This enables you to reference the container by
51
+ /// versions via `v1alpha1::Foo`.
52
+ /// 3. This `use` statement gives the generated containers access to the imports
53
+ /// at the top of the file. This is a convenience, because otherwise you
54
+ /// would need to prefix used items with `super::`. Additionally, other
55
+ /// macros can have trouble using items referred to with `super::`.
56
+ ///
57
+ /// ```ignore
58
+ /// #[automatically_derived] // 1
59
+ /// mod v1alpha1 { // 2
60
+ /// use super::*; // 3
61
+ /// pub struct Foo {
62
+ /// bar: usize,
63
+ /// }
64
+ /// }
65
+ /// ```
66
+ /// </details>
67
+ ///
68
+ /// ### Deprecation of a Version
39
69
///
40
- /// Before any of the fields can be versioned, versions need to be declared at
41
- /// the container level. Each version currently supports two parameters: `name`
42
- /// and the `deprecated` flag. The `name` must be a valid (and supported)
43
- /// format. The macro checks each declared version and reports any error
44
- /// encountered during parsing.
45
70
/// The `deprecated` flag marks the version as deprecated. This currently adds
46
71
/// the `#[deprecated]` attribute to the appropriate piece of code.
47
72
///
48
73
/// ```
49
74
/// # use stackable_versioned_macros::versioned;
50
- /// #[versioned(
51
- /// version(name = "v1alpha1", deprecated)
52
- /// )]
53
- /// struct Foo {}
75
+ /// #[versioned(version(name = "v1alpha1", deprecated))]
76
+ /// struct Foo {
77
+ /// bar: usize,
78
+ /// }
79
+ /// ```
80
+ ///
81
+ /// <details>
82
+ /// <summary>Generated code</summary>
83
+ ///
84
+ /// 1. The `deprecated` flag will generate a `#[deprecated]` attribute and the
85
+ /// note is automatically generated.
86
+ ///
87
+ /// ```ignore
88
+ /// #[automatically_derived]
89
+ /// #[deprecated = "Version v1alpha1 is deprecated"] // 1
90
+ /// mod v1alpha1 {
91
+ /// use super::*;
92
+ /// pub struct Foo {
93
+ /// pub bar: usize,
94
+ /// }
95
+ /// }
54
96
/// ```
97
+ /// </details>
98
+ ///
99
+ /// ### Version Sorting
55
100
///
56
101
/// Additionally, it is ensured that each version is unique. Declaring the same
57
102
/// version multiple times will result in an error. Furthermore, declaring the
@@ -65,37 +110,94 @@ mod consts;
65
110
/// version(name = "v1alpha1"),
66
111
/// options(allow_unsorted)
67
112
/// )]
68
- /// struct Foo {}
113
+ /// struct Foo {
114
+ /// bar: usize,
115
+ /// }
69
116
/// ```
70
117
///
71
- /// ### Field Actions
118
+ /// ## Item Actions
72
119
///
73
- /// This library currently supports three different field actions. Fields can
120
+ /// This library currently supports three different item actions. Items can
74
121
/// be added, renamed and deprecated. The macro ensures that these actions
75
122
/// adhere to the following set of rules:
76
123
///
77
- /// - Fields cannot be added and deprecated in the same version.
78
- /// - Fields cannot be added and renamed in the same version.
79
- /// - Fields cannot be renamed and deprecated in the same version.
80
- /// - Fields added in version _a_, renamed _0...n_ times in versions
81
- /// b<sub>1</sub>, b<sub>2</sub>, ..., b<sub>n</sub> and deprecated in
82
- /// version _c_ must ensure _a < b<sub>1</sub>, b<sub>2</sub>, ...,
83
- /// b<sub>n</sub> < c_.
84
- /// - All field actions must use previously declared versions. Using versions
85
- /// not present at the container level will result in an error.
124
+ /// 1. Items cannot be added and deprecated in the same version.
125
+ /// 2. Items cannot be added and changed in the same version.
126
+ /// 3. Items cannot be changed and deprecated in the same version.
127
+ /// 4. Items added in version _a_, renamed _0...n_ times in versions
128
+ /// b<sub>1</sub>, ..., b<sub>n</sub> and deprecated in
129
+ /// version _c_ must ensure _a < b<sub>1</sub>, ..., b<sub>n</sub> < c_.
130
+ /// 5. All item actions must use previously declared versions. Using versions
131
+ /// not present at the container level will result in an error.
86
132
///
87
- /// For fields marked as deprecated, two additional rules apply :
133
+ /// For items marked as deprecated, one additional rule applies :
88
134
///
89
- /// - Fields must start with the `deprecated_` prefix.
90
- /// - The deprecation note cannot be empty.
135
+ /// - Fields must start with the `deprecated_` and variants with the
136
+ /// `Deprecated` prefix. This is enforced because Kubernetes doesn't allow
137
+ /// removing fields in CRDs entirely. Instead, they should be marked as
138
+ /// deprecated. By convention this is done with the `deprecated` prefix.
91
139
///
92
- /// ### Auto-generated [`From`] Implementations
140
+ /// ### Added Action
141
+ ///
142
+ /// This action indicates that a item is added in a particular version.
143
+ /// Available parameters are:
93
144
///
94
- /// To enable smooth version upgrades of the same struct, the macro automatically
95
- /// generates [`From`] implementations. On a high level, code generated for two
96
- /// versions _a_ and _b_, with _a < b_ looks like this: `impl From<a> for b`.
145
+ /// - `since` to indicate since which version the item is present.
146
+ /// - `default_fn` to customize the default function used to populate the item
147
+ /// in auto-generated [`From`] implementations.
148
+ ///
149
+ /// ```
150
+ /// # use stackable_versioned_macros::versioned;
151
+ /// #[versioned(version(name = "v1alpha1"), version(name = "v1beta1"))]
152
+ /// pub struct Foo {
153
+ /// #[versioned(added(since = "v1beta1"))]
154
+ /// bar: usize,
155
+ /// baz: bool,
156
+ /// }
157
+ /// ```
158
+ ///
159
+ /// <details>
160
+ /// <summary>Generated code</summary>
161
+ ///
162
+ /// 1. The field `bar` is not yet present in version `v1alpha1` and is therefore
163
+ /// not generated.
164
+ /// 2. Now the field `bar` is present in version `v1beta1`.
97
165
///
98
166
/// ```ignore
167
+ /// pub mod v1alpha1 {
168
+ /// use super::*;
169
+ /// pub struct Foo { // 1
170
+ /// pub baz: bool,
171
+ /// }
172
+ /// }
173
+ ///
174
+ /// pub mod v1beta1 {
175
+ /// use super::*;
176
+ /// pub struct Foo {
177
+ /// pub bar: usize, // 2
178
+ /// pub baz: bool,
179
+ /// }
180
+ /// }
181
+ /// ```
182
+ /// </details>
183
+ ///
184
+ /// ### Changed Action
185
+ ///
186
+ /// TODO.
187
+ ///
188
+ /// ### Deprecated Action
189
+ ///
190
+ /// TODO.
191
+ ///
192
+ /// ### Auto-generated [`From`] Implementations
193
+ ///
194
+ /// To enable smooth version upgrades of the same container, the macro
195
+ /// automatically generates [`From`] implementations. On a high level, code
196
+ /// generated for two versions _a_ and _b_, with _a < b_ looks like this:
197
+ /// `impl From<a> for b`.
198
+ ///
199
+ /// ```
200
+ /// # use stackable_versioned_macros::versioned;
99
201
/// #[versioned(
100
202
/// version(name = "v1alpha1"),
101
203
/// version(name = "v1beta1"),
@@ -104,62 +206,78 @@ mod consts;
104
206
/// pub struct Foo {
105
207
/// #[versioned(
106
208
/// added(since = "v1beta1"),
107
- /// deprecated(since = "v1", note = "not needed" )
209
+ /// deprecated(since = "v1")
108
210
/// )]
109
211
/// deprecated_bar: usize,
110
212
/// baz: bool,
111
213
/// }
214
+ /// ```
112
215
///
113
- /// // Produces ...
216
+ /// <details>
217
+ /// <summary>Generated code</summary>
114
218
///
115
- /// #[automatically_derived]
219
+ /// 1. The field `bar` is not yet present in version `v1alpha1` and is therefore
220
+ /// not generated.
221
+ /// 2. Now the field `bar` is present and uses `Default::default()` to populate
222
+ /// the field during conversion. This function can be customized as shown
223
+ /// later in this guide.
224
+ /// 3. In version `v1` the field `bar` is deprecated and as such includes the
225
+ /// `deprecated_` prefix. Additionally, the `#[deprecated]` attribute is
226
+ /// added to indicate that this part of the Rust code is deprecated. The
227
+ /// note is optional.
228
+ ///
229
+ /// ```ignore
116
230
/// pub mod v1alpha1 {
117
- /// pub struct Foo {
231
+ /// use super::*;
232
+ /// pub struct Foo { // 1
118
233
/// pub baz: bool,
119
234
/// }
120
235
/// }
121
- /// #[automatically_derived]
122
- /// #[allow(deprecated)]
236
+ ///
123
237
/// impl From<v1alpha1::Foo> for v1beta1::Foo {
124
238
/// fn from(__sv_foo: v1alpha1::Foo) -> Self {
125
239
/// Self {
126
- /// bar: std::default::Default::default(),
240
+ /// bar: :: std::default::Default::default(), // 2
127
241
/// baz: __sv_foo.baz,
128
242
/// }
129
243
/// }
130
244
/// }
131
- /// #[automatically_derived]
245
+ ///
132
246
/// pub mod v1beta1 {
247
+ /// use super::*;
133
248
/// pub struct Foo {
134
249
/// pub bar: usize,
135
250
/// pub baz: bool,
136
251
/// }
137
252
/// }
138
- /// #[automatically_derived]
139
- /// #[allow(deprecated)]
253
+ ///
140
254
/// impl From<v1beta1::Foo> for v1::Foo {
141
255
/// fn from(__sv_foo: v1beta1::Foo) -> Self {
142
256
/// Self {
143
- /// deprecated_bar: __sv_foo.bar,
257
+ /// deprecated_bar: __sv_foo.bar, // 3
144
258
/// baz: __sv_foo.baz,
145
259
/// }
146
260
/// }
147
261
/// }
148
- /// #[automatically_derived]
262
+ ///
149
263
/// pub mod v1 {
264
+ /// use super::*;
150
265
/// pub struct Foo {
151
- /// #[deprecated = "not needed"]
266
+ /// #[deprecated] // 3
152
267
/// pub deprecated_bar: usize,
153
268
/// pub baz: bool,
154
269
/// }
155
270
/// }
156
271
/// ```
272
+ /// </details>
273
+ ///
274
+ /// ### Skip [`From`] Generation
157
275
///
158
- /// #### Skip [`From`] generation
276
+ /// Generation of auto-generated [`From`] implementations can be skipped at the
277
+ /// container and version level. This enables customization of the
278
+ /// implementations if the default implementation is not sufficient.
159
279
///
160
- /// Generation of these [`From`] implementations can be skipped at the container
161
- /// and version level. This enables customization of the implementations if the
162
- /// default implementation is not sufficient.
280
+ /// #### Skipping at the Container Level
163
281
///
164
282
/// ```
165
283
/// # use stackable_versioned_macros::versioned;
@@ -179,7 +297,7 @@ mod consts;
179
297
/// }
180
298
/// ```
181
299
///
182
- /// #### Customize Default Function for Added Fields
300
+ /// ### Customize Default Function for Added Fields
183
301
///
184
302
/// It is possible to customize the default function used in the generated
185
303
/// [`From`] implementation for populating added fields. By default,
0 commit comments