pub trait Enum: Reflect {
Show 14 methods
// Required methods
fn field(&self, name: &str) -> Option<&(dyn Reflect + 'static)>;
fn field_at(&self, index: usize) -> Option<&(dyn Reflect + 'static)>;
fn field_mut(&mut self, name: &str) -> Option<&mut (dyn Reflect + 'static)>;
fn field_at_mut(
&mut self,
index: usize
) -> Option<&mut (dyn Reflect + 'static)>;
fn index_of(&self, name: &str) -> Option<usize>;
fn name_at(&self, index: usize) -> Option<&str>;
fn iter_fields(&self) -> VariantFieldIter<'_> ⓘ;
fn field_len(&self) -> usize;
fn variant_name(&self) -> &str;
fn variant_index(&self) -> usize;
fn variant_type(&self) -> VariantType;
fn clone_dynamic(&self) -> DynamicEnum;
// Provided methods
fn is_variant(&self, variant_type: VariantType) -> bool { ... }
fn variant_path(&self) -> String { ... }
}
Expand description
A trait used to power enum-like operations via reflection.
This allows enums to be processed and modified dynamically at runtime without necessarily knowing the actual type. Enums are much more complex than their struct counterparts. As a result, users will need to be mindful of conventions, considerations, and complications when working with this trait.
Variants
An enum is a set of choices called variants.
An instance of an enum can only exist as one of these choices at any given time.
Consider Rust’s Option<T>
. It’s an enum with two variants: None
and Some
.
If you’re None
, you can’t be Some
and vice versa.
⚠️ This is very important: The
Enum
trait represents an enum as one of its variants. It does not represent the entire enum since that’s not true to how enums work.
Variants come in a few flavors:
Variant Type | Syntax |
---|---|
Unit | MyEnum::Foo |
Tuple | MyEnum::Foo( i32, i32 ) |
Struct | MyEnum::Foo{ value: String } |
As you can see, a unit variant contains no fields, while tuple and struct variants
can contain one or more fields.
The fields in a tuple variant is defined by their order within the variant.
Index 0
represents the first field in the variant and so on.
Fields in struct variants (excluding tuple structs), on the other hand, are
represented by a name.
Implementation
💡 This trait can be automatically implemented using
#[derive(Reflect)]
on an enum definition.
Despite the fact that enums can represent multiple states, traits only exist in one state
and must be applied to the entire enum rather than a particular variant.
Because of this limitation, the Enum
trait must not only represent any of the
three variant types, but also define the methods for all three as well.
What does this mean? It means that even though a unit variant contains no fields, a
representation of that variant using the Enum
trait will still contain methods for
accessing fields!
Again, this is to account for all three variant types.
We recommend using the built-in #[derive(Reflect)]
macro to automatically handle all the
implementation details for you.
However, if you must implement this trait manually, there are a few things to keep in mind…
Field Order
While tuple variants identify their fields by the order in which they are defined, struct variants identify fields by their name. However, both should allow access to fields by their defined order.
The reason all fields, regardless of variant type, need to be accessible by their order is due to field iteration. We need a way to iterate through each field in a variant, and the easiest way of achieving that is through the use of field order.
The derive macro adds proper struct variant handling for Enum::index_of
, Enum::name_at
and Enum::field_at[_mut]
methods.
The first two methods are required for all struct variant types.
By convention, implementors should also handle the last method as well, but this is not
a strict requirement.
Field Names
Implementors may choose to handle Enum::index_of
, Enum::name_at
, and
Enum::field[_mut]
for tuple variants by considering stringified usize
s to be
valid names (such as "3"
).
This isn’t wrong to do, but the convention set by the derive macro is that it isn’t supported.
It’s preferred that these strings be converted to their proper usize
representations and
the Enum::field_at[_mut]
methods be used instead.
Required Methods§
sourcefn field(&self, name: &str) -> Option<&(dyn Reflect + 'static)>
fn field(&self, name: &str) -> Option<&(dyn Reflect + 'static)>
Returns a reference to the value of the field (in the current variant) with the given name.
For non-VariantType::Struct
variants, this should return None
.
sourcefn field_at(&self, index: usize) -> Option<&(dyn Reflect + 'static)>
fn field_at(&self, index: usize) -> Option<&(dyn Reflect + 'static)>
Returns a reference to the value of the field (in the current variant) at the given index.
sourcefn field_mut(&mut self, name: &str) -> Option<&mut (dyn Reflect + 'static)>
fn field_mut(&mut self, name: &str) -> Option<&mut (dyn Reflect + 'static)>
Returns a mutable reference to the value of the field (in the current variant) with the given name.
For non-VariantType::Struct
variants, this should return None
.
sourcefn field_at_mut(&mut self, index: usize) -> Option<&mut (dyn Reflect + 'static)>
fn field_at_mut(&mut self, index: usize) -> Option<&mut (dyn Reflect + 'static)>
Returns a mutable reference to the value of the field (in the current variant) at the given index.
sourcefn index_of(&self, name: &str) -> Option<usize>
fn index_of(&self, name: &str) -> Option<usize>
Returns the index of the field (in the current variant) with the given name.
For non-VariantType::Struct
variants, this should return None
.
sourcefn name_at(&self, index: usize) -> Option<&str>
fn name_at(&self, index: usize) -> Option<&str>
Returns the name of the field (in the current variant) with the given index.
For non-VariantType::Struct
variants, this should return None
.
sourcefn iter_fields(&self) -> VariantFieldIter<'_> ⓘ
fn iter_fields(&self) -> VariantFieldIter<'_> ⓘ
Returns an iterator over the values of the current variant’s fields.
sourcefn variant_name(&self) -> &str
fn variant_name(&self) -> &str
The name of the current variant.
sourcefn variant_index(&self) -> usize
fn variant_index(&self) -> usize
The index of the current variant.
sourcefn variant_type(&self) -> VariantType
fn variant_type(&self) -> VariantType
The type of the current variant.
fn clone_dynamic(&self) -> DynamicEnum
Provided Methods§
sourcefn is_variant(&self, variant_type: VariantType) -> bool
fn is_variant(&self, variant_type: VariantType) -> bool
Returns true if the current variant’s type matches the given one.
sourcefn variant_path(&self) -> String
fn variant_path(&self) -> String
Returns the full path to the current variant.