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
//! A trait and declarative macro for iterating through `enum` variants.
//!
//! ## The Problem
//!
//! If an `enum` type in Rust contains zero or more variants that have no
//! fields, it would be valid to iterate through each of these variants.
//! Unfortunately, there is not an easy way to achieve this.
//!
//! ```
//! // A suboptimal solution...
//! enum Status {
//! Complete,
//! Error,
//! }
//!
//! impl Status {
//! // not a robust solution, requires tweaking whenever a variant is added or removed
//! // this computation is also invalidated if any of the variants receive fields
//! fn get_variants() -> &'static [Self] { &[Status::Complete, Status::Error] }
//! }
//! ```
//!
//! ## The Solution
//!
//! `variter` provides a trait [`VarIter`] that gives you the opportunity to
//! define an associated constant that returns `&'static [Self]`. This trait
//! alone won't help much on its own, but the macro [`derive_var_iter!`] can
//! wrap your `enum` declarations and implement [`VarIter`] for you. As cases
//! are added or removed, the implementation is automatically updated.
//!
//! ```
//! use variter::{derive_var_iter, VarIter};
//! derive_var_iter! {
//! #[derive(Debug, PartialEq, Eq)]
//! enum Status {
//! Complete,
//! Error,
//! }
//! }
//! assert_eq!(Status::ALL_VARIANTS.len(), 2);
//! assert!(Status::ALL_VARIANTS.contains(&Status::Error));
//! assert!(Status::ALL_VARIANTS.contains(&Status::Complete));
//! ```
//!
//! ## What about a `#[derive]` macro?
//!
//! `#[derive]` macros are great, but many IDEs and editors don't support
//! autocompletion capabilities for traits derived in this way, except for the
//! builtin traits, and possibly [`serde`] traits. On the other hand, many IDEs
//! and editors can expand declarative macros in place and offer autocompletion
//! and other hints.
//!
//! ## Manual Implementations
//!
//! It is not recommended to implement [`VarIter`] manually for the following
//! reasons:
//! - Manual implementations need to be updated as variants are added or
//! removed.
//! - Implementing [`VarIter`] on incorrect types is a logical error. Invalid
//! types include:
//! - `structs`
//! - `enum`s where any variant contains a field, such as `Case1(i32)` or
//! `Case2 { x: usize }`
//! - `enum`s marked with the `#[non_exhaustive]` attribute
//! - Using [`derive_var_iter!`] results in a compile-time error if appiled to
//! the above types (albeit with an unhelpful error message!) *except* for
//! `#[non_exhaustive]` `enum`s!
//!
//! ## Additionally...
//!
//! This crate exports an additional macro [`foreign_derive_var_iter!`] for
//! implementing [`VarIter`] on foreign types. The crate also implements
//! [`VarIter`] on stable, field-less enums from [`core`] and [`std`] through
//! the `foreign_impls` feature flag.
//!
//! [`serde`]: https://serde.rs/
//! [`core]: https://doc.rust-lang.org/stable/core/index.html
//! [`std`]: https://doc.rust-lang.org/stable/std/index.html
doctest!;
/// A trait for field-less `enum`s that gives access to each of its variants.
///
/// ```
/// use variter::{derive_var_iter, VarIter};
/// derive_var_iter! {
/// enum CardSuit {
/// Clubs,
/// Spades,
/// Hearts,
/// Diamonds,
/// }
/// }
/// use CardSuit::*;
/// print!("Card suits: ");
/// for suit in CardSuit::ALL_VARIANTS {
/// let symbol = match suit {
/// Clubs => '\u{2664}',
/// Hearts => '\u{2661}',
/// Spades => '\u{2667}',
/// Diamonds => '\u{2662}',
/// };
/// print!("{} ", symbol);
/// }
/// println!();
/// ```
/// Automatically derive [`VarIter`] for your field-less `enum`s. Multiple
/// `enum` declarations can be included inside the macro.
///
/// You may optionally pass attributes to the `impl` block by prefixing your
/// type definition with `@impl_attr { ATTR... }`, for example `@impl_attr {
/// #[doc(hidden)] #[cfg(test)] ... }`.
///
/// ```
/// use variter::{derive_var_iter, VarIter};
/// derive_var_iter! {
/// @impl_attr {
/// #[doc(hidden)]
/// }
/// enum Empty {}
///
/// pub enum TwoChoice {
/// First,
/// Second
/// }
///
/// #[derive(Debug)]
/// pub(crate) enum CoinFlip {
/// Heads,
/// Tails
/// }
/// }
/// for var in CoinFlip::ALL_VARIANTS {
/// println!("{:?}", var);
/// }
/// ```
$*
) => ;
// One or more variants
=> ;
=> ;
}
/// Automatically derive [`VarIter`] for foreign field-less `enums`. Be sure to
/// include all variants and that the `enum` is *not* marked with `#[non_exhaustive]`.
///
/// ## Syntax
///
/// ```text
/// foreign_derive_var_iter! {
/// Typename [] // enum has no variants
/// Typename [Typename::Variant1, Typename::variant2, ... ] // trailing comma supported
/// ...
/// }
/// ```
///
/// You may optionally pass attributes to the `impl` block by prefixing your
/// type definition with `@impl_attr { ATTR... }`, for example `@impl_attr {
/// #[doc(hidden)] #[cfg(test)] ... }`.
foreign_derive_var_iter!;
};
// One or more variants
=> ;
=> ;
}