facet_core/types/
enum_.rs

1use super::Struct;
2
3/// Fields for enum types
4#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
5#[repr(C)]
6#[non_exhaustive]
7pub struct EnumDef {
8    /// representation of the enum (u8, u16, etc.)
9    pub repr: EnumRepr,
10
11    /// all variants for this enum
12    pub variants: &'static [Variant],
13}
14
15impl EnumDef {
16    /// Returns a builder for EnumDef
17    pub const fn builder() -> EnumDefBuilder {
18        EnumDefBuilder::new()
19    }
20}
21
22/// Builder for EnumDef
23pub struct EnumDefBuilder {
24    repr: Option<EnumRepr>,
25    variants: Option<&'static [Variant]>,
26}
27
28impl EnumDefBuilder {
29    /// Creates a new EnumDefBuilder
30    #[allow(clippy::new_without_default)]
31    pub const fn new() -> Self {
32        Self {
33            repr: None,
34            variants: None,
35        }
36    }
37
38    /// Sets the representation for the EnumDef
39    pub const fn repr(mut self, repr: EnumRepr) -> Self {
40        self.repr = Some(repr);
41        self
42    }
43
44    /// Sets the variants for the EnumDef
45    pub const fn variants(mut self, variants: &'static [Variant]) -> Self {
46        self.variants = Some(variants);
47        self
48    }
49
50    /// Builds the EnumDef
51    pub const fn build(self) -> EnumDef {
52        EnumDef {
53            repr: self.repr.unwrap(),
54            variants: self.variants.unwrap(),
55        }
56    }
57}
58
59/// Describes a variant of an enum
60#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
61#[repr(C)]
62#[non_exhaustive]
63pub struct Variant {
64    /// Name of the variant, e.g. `Foo` for `enum FooBar { Foo, Bar }`
65    pub name: &'static str,
66
67    /// Discriminant value (if available). Might fit in a u8, etc.
68    pub discriminant: i64,
69
70    /// Fields for this variant (empty if unit, number-named if tuple).
71    /// IMPORTANT: the offset for the fields already takes into account the size & alignment of the
72    /// discriminant.
73    pub data: Struct,
74
75    /// Doc comment for the variant
76    pub doc: &'static [&'static str],
77}
78
79impl Variant {
80    /// Returns a builder for Variant
81    pub const fn builder() -> VariantBuilder {
82        VariantBuilder::new()
83    }
84}
85
86/// Builder for Variant
87pub struct VariantBuilder {
88    name: Option<&'static str>,
89    discriminant: Option<i64>,
90    fields: Option<Struct>,
91    doc: &'static [&'static str],
92}
93
94impl VariantBuilder {
95    /// Creates a new VariantBuilder
96    #[allow(clippy::new_without_default)]
97    pub const fn new() -> Self {
98        Self {
99            name: None,
100            discriminant: None,
101            fields: None,
102            doc: &[],
103        }
104    }
105
106    /// Sets the name for the Variant
107    pub const fn name(mut self, name: &'static str) -> Self {
108        self.name = Some(name);
109        self
110    }
111
112    /// Sets the discriminant for the Variant
113    pub const fn discriminant(mut self, discriminant: i64) -> Self {
114        self.discriminant = Some(discriminant);
115        self
116    }
117
118    /// Sets the fields for the Variant
119    pub const fn fields(mut self, fields: Struct) -> Self {
120        self.fields = Some(fields);
121        self
122    }
123
124    /// Sets the doc comment for the Variant
125    pub const fn doc(mut self, doc: &'static [&'static str]) -> Self {
126        self.doc = doc;
127        self
128    }
129
130    /// Builds the Variant
131    pub const fn build(self) -> Variant {
132        Variant {
133            name: self.name.unwrap(),
134            discriminant: self.discriminant.unwrap(),
135            data: self.fields.unwrap(),
136            doc: self.doc,
137        }
138    }
139}
140
141/// All possible representations for Rust enums — ie. the type/size of the discriminant
142#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
143#[repr(C)]
144#[non_exhaustive]
145pub enum EnumRepr {
146    /// u8 representation (#[repr(u8)])
147    U8,
148    /// u16 representation (#[repr(u16)])
149    U16,
150    /// u32 representation (#[repr(u32)])
151    U32,
152    /// u64 representation (#[repr(u64)])
153    U64,
154    /// usize representation (#[repr(usize)])
155    USize,
156    /// i8 representation (#[repr(i8)])
157    I8,
158    /// i16 representation (#[repr(i16)])
159    I16,
160    /// i32 representation (#[repr(i32)])
161    I32,
162    /// i64 representation (#[repr(i64)])
163    I64,
164    /// isize representation (#[repr(isize)])
165    ISize,
166}
167
168impl EnumRepr {
169    /// Returns the enum representation for the given discriminant type
170    ///
171    /// NOTE: only supports unsigned discriminants
172    ///
173    /// # Panics
174    ///
175    /// Panics if the size of the discriminant size is not 1, 2, 4, or 8 bytes.
176    pub const fn from_discriminant_size<T>() -> Self {
177        match core::mem::size_of::<T>() {
178            1 => EnumRepr::U8,
179            2 => EnumRepr::U16,
180            4 => EnumRepr::U32,
181            8 => EnumRepr::U64,
182            _ => panic!("Invalid enum size"),
183        }
184    }
185}