pod_enum/
lib.rs

1//! Make an enum which can act like plain-old-data
2//!
3//! See [`pod_enum`] for details.
4
5#![no_std]
6
7#[doc(hidden)]
8pub use bytemuck;
9
10/// Make a plain-old-data enum
11///
12/// This macro changes the enum to allow for "unknown" variants which take the discriminant
13/// values not listed in the definition, thus allowing the enum to be valid for any bit pattern
14/// and have no uninitialized bytes. We also implement [`bytemuck::Pod`] for the enum, since it
15/// meets those guarantees.
16///
17/// The representation of the enum must be specified as a type (any of the `repr(u*)` or
18/// `repr(i*)` types are supported, not `repr(C)` or `repr(Rust)`). The enum will have the same
19/// size and alignment as the given representation.
20///
21/// The resulting type also gets implementations of [`Debug`](core::fmt::Debug) and
22/// [`PartialEq`].
23///
24/// # Example
25/// ```
26/// use pod_enum::pod_enum;
27///
28/// /// An example enum
29/// #[pod_enum]
30/// #[repr(u8)]
31/// enum Foo {
32///     /// Bar
33///     Bar = 0,
34///     Bat = 1,
35///     Baz = 2,
36/// }
37///
38/// assert_eq!(Foo::from(0), Foo::Bar);
39/// assert_eq!(u8::from(Foo::Bat), 1);
40/// assert_eq!(&format!("{:?}", Foo::Baz), "Baz");
41/// assert_eq!(&format!("{:?}", Foo::from(3)), "Unknown (3)");
42/// ```
43///
44/// Note that all variants of the enum must have an explicitly annotated discriminant, and no
45/// fields may be listed on any of the variants.
46///
47/// # Safety
48/// This macro checks that the internal representation used is [`bytemuck::Pod`], and will
49/// return an error otherwise. There is no risk of unsound code being generated.
50/// ```compile_fail
51/// use core::num::NonZeroU8;
52/// use pod_enum::pod_enum;
53///
54/// #[pod_enum]
55/// // This is not allowed - `bool` has invalid bit patterns
56/// #[repr(bool)]
57/// enum Foo {
58///     Bar = false,
59/// }
60/// ```
61pub use pod_enum_macros::pod_enum;
62
63/// A trait marking this type as a plain-old-data enum
64///
65/// This is intended to be implemented by the [`pod_enum`] attribute macro, not to be
66/// implemented on its own.
67pub trait PodEnum: bytemuck::Pod {
68    /// The type used for the internal representation
69    type Repr: bytemuck::Pod;
70}