142 | //!
143 | //! **Warning**: `open_enum` may change the automatic integer representation for a given enum
144 | //! in a future version with a minor version bump - it is not considered a breaking change.
145 | //! Do not depend on this type remaining stable - use an explicit `#[repr]` for stability.
146 | //!
147 | //!
148 | //!
149 | //! [^its-all-isize]: Like regular `enum`s, the declared discriminant for enums without an explicit `repr`
150 | //! is interpreted as an `isize` regardless of the automatic storage type chosen.
151 | //!
152 | //! [^nonliterals-are-hard]: This optimization fails if the `enum` declares a non-literal constant expression
153 | //! as one of its discriminant values, and falls back to `isize`. To avoid this, specify an explicit `repr`.
154 | //!
155 | //! [^repr-c-weird]: Note that this might not actually be the correct default `enum` size for C on all platforms,
156 | //! since the [compiler could choose something smaller than `int`](https://stackoverflow.com/a/366026).
157 | //!
158 | //! [^repr-c-feature]: This requires either the `std` or `libc_` feature (note the underscore)
159 | //!
160 | //! ## Aliasing variants
161 | //! Regular `enum`s cannot have multiple variants with the same discriminant.
162 | //! However, since `open_enum` produces associated constants, multiple
163 | //! names can represent the same integer value. By default, `open_enum`
164 | //! rejects aliasing variants, but it can be allowed with the `allow_alias` option:
165 | //!
166 | //! ```
167 | //! # use open_enum::open_enum;
168 | //! #[open_enum(allow_alias)]
169 | //! #[derive(Debug)]
170 | //! enum Character {
171 | //! Viola = 0,
172 | //! Cesario = 0,
173 | //! Sebastian,
174 | //! Orsino,
175 | //! Olivia,
176 | //! Malvolio,
177 | //! }
178 | //!
179 | //! assert_eq!(Character::Viola, Character::Cesario);
180 | //!
181 | //! ```
182 | //!
183 | //!
184 | //!
185 | //! # Custom debug implementation
186 | //! `open_enum` will generate a debug implementation that mirrors the standard `#[derive(Debug)]` for normal Rust enums
187 | //! by printing the name of the variant rather than the value contained, if the value is a named variant.
188 | //!
189 | //! However, if an enum has `#[open_enum(allow_alias)]` specified, the debug representation will be the numeric value only.
190 | //!
191 | //! For example, this given enum,
192 | //! ```
193 | //! # use open_enum::open_enum;
194 | //! #[open_enum]
195 | //! #[derive(Debug)]
196 | //! enum Fruit {
197 | //! Apple,
198 | //! Pear,
199 | //! Banana,
200 | //! Blueberry = 5,
201 | //! Raspberry,
202 | //! }
203 | //! ```
204 | //!
205 | //! will have the following debug implementation emitted:
206 | //! ```
207 | //! # use open_enum::open_enum;
208 | //! # #[open_enum]
209 | //! # enum Fruit {
210 | //! # Apple,
211 | //! # Pear,
212 | //! # Banana,
213 | //! # Blueberry = 5,
214 | //! # Raspberry,
215 | //! # }
216 | //! # impl ::core::fmt::Debug for Fruit {
217 | //! fn fmt(&self, fmt: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
218 | //! #![allow(unreachable_patterns)]
219 | //! let s = match *self {
220 | //! Self::Apple => stringify!(Apple),
221 | //! Self::Pear => stringify!(Pear),
222 | //! Self::Banana => stringify!(Banana),
223 | //! Self::Blueberry => stringify!(Blueberry),
224 | //! Self::Raspberry => stringify!(Raspberry),
225 | //! _ => {
226 | //! return fmt.debug_tuple(stringify!(Fruit)).field(&self.0).finish();
227 | //! }
228 | //! };
229 | //! fmt.pad(s)
230 | //! }
231 | //! # }
232 | //! ```
233 | //!
234 | //! # Compared with `#[non_exhuastive]`
235 | //! The [`non_exhaustive`][non-exhaustive] attribute indicates that a type or variant
236 | //! may have more fields or variants added in the future. When applied to an `enum` (not its variants),
237 | //! it requires that foreign crates provide a wildcard arm when `match`ing.
238 | //! Since open enums are inherently non-exhaustive[^mostly-non-exhaustive], this attribute is incompatible
239 | //! with `open_enum`. Unlike `non_exhaustive`, open enums also require a wildcard branch on `match`es in
240 | //! the defining crate.
241 | //!
242 | //! [^mostly-non-exhaustive]: Unless the enum defines a variant for every value of its underlying integer.
243 | //!
244 | //! # Disadvantages of open enums
245 | //! - The kind listed in the source code, an `enum`, is not the same as the actual output, a `struct`,
246 | //! which could be confusing or hard to debug, since its usage is similar, but not exactly the same.
247 | //! - No niche optimization: `Option