bevy_reflect/enums/
variants.rs

1use crate::attributes::{impl_custom_attribute_methods, CustomAttributes};
2use crate::{NamedField, UnnamedField};
3use bevy_utils::HashMap;
4use std::slice::Iter;
5use std::sync::Arc;
6
7/// Describes the form of an enum variant.
8#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
9pub enum VariantType {
10    /// Struct enums take the form:
11    ///
12    /// ```
13    /// enum MyEnum {
14    ///   A {
15    ///     foo: usize
16    ///   }
17    /// }
18    /// ```
19    Struct,
20    /// Tuple enums take the form:
21    ///
22    /// ```
23    /// enum MyEnum {
24    ///   A(usize)
25    /// }
26    /// ```
27    Tuple,
28    /// Unit enums take the form:
29    ///
30    /// ```
31    /// enum MyEnum {
32    ///   A
33    /// }
34    /// ```
35    Unit,
36}
37
38/// A container for compile-time enum variant info.
39#[derive(Clone, Debug)]
40pub enum VariantInfo {
41    /// Struct enums take the form:
42    ///
43    /// ```
44    /// enum MyEnum {
45    ///   A {
46    ///     foo: usize
47    ///   }
48    /// }
49    /// ```
50    Struct(StructVariantInfo),
51    /// Tuple enums take the form:
52    ///
53    /// ```
54    /// enum MyEnum {
55    ///   A(usize)
56    /// }
57    /// ```
58    Tuple(TupleVariantInfo),
59    /// Unit enums take the form:
60    ///
61    /// ```
62    /// enum MyEnum {
63    ///   A
64    /// }
65    /// ```
66    Unit(UnitVariantInfo),
67}
68
69impl VariantInfo {
70    pub fn name(&self) -> &'static str {
71        match self {
72            Self::Struct(info) => info.name(),
73            Self::Tuple(info) => info.name(),
74            Self::Unit(info) => info.name(),
75        }
76    }
77
78    /// The docstring of the underlying variant, if any.
79    #[cfg(feature = "documentation")]
80    pub fn docs(&self) -> Option<&str> {
81        match self {
82            Self::Struct(info) => info.docs(),
83            Self::Tuple(info) => info.docs(),
84            Self::Unit(info) => info.docs(),
85        }
86    }
87
88    impl_custom_attribute_methods!(
89        self,
90        match self {
91            Self::Struct(info) => info.custom_attributes(),
92            Self::Tuple(info) => info.custom_attributes(),
93            Self::Unit(info) => info.custom_attributes(),
94        },
95        "variant"
96    );
97}
98
99/// Type info for struct variants.
100#[derive(Clone, Debug)]
101pub struct StructVariantInfo {
102    name: &'static str,
103    fields: Box<[NamedField]>,
104    field_names: Box<[&'static str]>,
105    field_indices: HashMap<&'static str, usize>,
106    custom_attributes: Arc<CustomAttributes>,
107    #[cfg(feature = "documentation")]
108    docs: Option<&'static str>,
109}
110
111impl StructVariantInfo {
112    /// Create a new [`StructVariantInfo`].
113    pub fn new(name: &'static str, fields: &[NamedField]) -> Self {
114        let field_indices = Self::collect_field_indices(fields);
115        let field_names = fields.iter().map(|field| field.name()).collect();
116        Self {
117            name,
118            fields: fields.to_vec().into_boxed_slice(),
119            field_names,
120            field_indices,
121            custom_attributes: Arc::new(CustomAttributes::default()),
122            #[cfg(feature = "documentation")]
123            docs: None,
124        }
125    }
126
127    /// Sets the docstring for this variant.
128    #[cfg(feature = "documentation")]
129    pub fn with_docs(self, docs: Option<&'static str>) -> Self {
130        Self { docs, ..self }
131    }
132
133    /// Sets the custom attributes for this variant.
134    pub fn with_custom_attributes(self, custom_attributes: CustomAttributes) -> Self {
135        Self {
136            custom_attributes: Arc::new(custom_attributes),
137            ..self
138        }
139    }
140
141    /// The name of this variant.
142    pub fn name(&self) -> &'static str {
143        self.name
144    }
145
146    /// A slice containing the names of all fields in order.
147    pub fn field_names(&self) -> &[&'static str] {
148        &self.field_names
149    }
150
151    /// Get the field with the given name.
152    pub fn field(&self, name: &str) -> Option<&NamedField> {
153        self.field_indices
154            .get(name)
155            .map(|index| &self.fields[*index])
156    }
157
158    /// Get the field at the given index.
159    pub fn field_at(&self, index: usize) -> Option<&NamedField> {
160        self.fields.get(index)
161    }
162
163    /// Get the index of the field with the given name.
164    pub fn index_of(&self, name: &str) -> Option<usize> {
165        self.field_indices.get(name).copied()
166    }
167
168    /// Iterate over the fields of this variant.
169    pub fn iter(&self) -> Iter<'_, NamedField> {
170        self.fields.iter()
171    }
172
173    /// The total number of fields in this variant.
174    pub fn field_len(&self) -> usize {
175        self.fields.len()
176    }
177
178    fn collect_field_indices(fields: &[NamedField]) -> HashMap<&'static str, usize> {
179        fields
180            .iter()
181            .enumerate()
182            .map(|(index, field)| (field.name(), index))
183            .collect()
184    }
185
186    /// The docstring of this variant, if any.
187    #[cfg(feature = "documentation")]
188    pub fn docs(&self) -> Option<&'static str> {
189        self.docs
190    }
191
192    impl_custom_attribute_methods!(self.custom_attributes, "variant");
193}
194
195/// Type info for tuple variants.
196#[derive(Clone, Debug)]
197pub struct TupleVariantInfo {
198    name: &'static str,
199    fields: Box<[UnnamedField]>,
200    custom_attributes: Arc<CustomAttributes>,
201    #[cfg(feature = "documentation")]
202    docs: Option<&'static str>,
203}
204
205impl TupleVariantInfo {
206    /// Create a new [`TupleVariantInfo`].
207    pub fn new(name: &'static str, fields: &[UnnamedField]) -> Self {
208        Self {
209            name,
210            fields: fields.to_vec().into_boxed_slice(),
211            custom_attributes: Arc::new(CustomAttributes::default()),
212            #[cfg(feature = "documentation")]
213            docs: None,
214        }
215    }
216
217    /// Sets the docstring for this variant.
218    #[cfg(feature = "documentation")]
219    pub fn with_docs(self, docs: Option<&'static str>) -> Self {
220        Self { docs, ..self }
221    }
222
223    /// Sets the custom attributes for this variant.
224    pub fn with_custom_attributes(self, custom_attributes: CustomAttributes) -> Self {
225        Self {
226            custom_attributes: Arc::new(custom_attributes),
227            ..self
228        }
229    }
230
231    /// The name of this variant.
232    pub fn name(&self) -> &'static str {
233        self.name
234    }
235
236    /// Get the field at the given index.
237    pub fn field_at(&self, index: usize) -> Option<&UnnamedField> {
238        self.fields.get(index)
239    }
240
241    /// Iterate over the fields of this variant.
242    pub fn iter(&self) -> Iter<'_, UnnamedField> {
243        self.fields.iter()
244    }
245
246    /// The total number of fields in this variant.
247    pub fn field_len(&self) -> usize {
248        self.fields.len()
249    }
250
251    /// The docstring of this variant, if any.
252    #[cfg(feature = "documentation")]
253    pub fn docs(&self) -> Option<&'static str> {
254        self.docs
255    }
256
257    impl_custom_attribute_methods!(self.custom_attributes, "variant");
258}
259
260/// Type info for unit variants.
261#[derive(Clone, Debug)]
262pub struct UnitVariantInfo {
263    name: &'static str,
264    custom_attributes: Arc<CustomAttributes>,
265    #[cfg(feature = "documentation")]
266    docs: Option<&'static str>,
267}
268
269impl UnitVariantInfo {
270    /// Create a new [`UnitVariantInfo`].
271    pub fn new(name: &'static str) -> Self {
272        Self {
273            name,
274            custom_attributes: Arc::new(CustomAttributes::default()),
275            #[cfg(feature = "documentation")]
276            docs: None,
277        }
278    }
279
280    /// Sets the docstring for this variant.
281    #[cfg(feature = "documentation")]
282    pub fn with_docs(self, docs: Option<&'static str>) -> Self {
283        Self { docs, ..self }
284    }
285
286    /// Sets the custom attributes for this variant.
287    pub fn with_custom_attributes(self, custom_attributes: CustomAttributes) -> Self {
288        Self {
289            custom_attributes: Arc::new(custom_attributes),
290            ..self
291        }
292    }
293
294    /// The name of this variant.
295    pub fn name(&self) -> &'static str {
296        self.name
297    }
298
299    /// The docstring of this variant, if any.
300    #[cfg(feature = "documentation")]
301    pub fn docs(&self) -> Option<&'static str> {
302        self.docs
303    }
304
305    impl_custom_attribute_methods!(self.custom_attributes, "variant");
306}