138 lines
4.7 KiB
Rust
138 lines
4.7 KiB
Rust
|
use super::Reflect;
|
||
|
|
||
|
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
||
|
pub enum EnumType {
|
||
|
Unit,
|
||
|
Tuple,
|
||
|
Struct,
|
||
|
}
|
||
|
|
||
|
pub trait Enum: Reflect {
|
||
|
/// Returns the enum item matching the **lowercase** name.
|
||
|
///
|
||
|
/// Will return None if the item is not in this struct, or if the num is not an instance of
|
||
|
/// the item matching the name. See [`Enum::has_item`] for seeing if the item exists.
|
||
|
fn field(&self, name: &str) -> Option<&dyn Reflect>;
|
||
|
|
||
|
/// Returns the enum item matching the **lowercase** name.
|
||
|
///
|
||
|
/// Will return None if the item is not in this struct, or if the num is not an instance of
|
||
|
/// the item matching the name. See [`Enum::has_item`] for seeing if the item exists.
|
||
|
fn field_mut(&mut self, name: &str) -> Option<&mut dyn Reflect>;
|
||
|
|
||
|
fn field_at(&self, idx: usize) -> Option<&dyn Reflect>;
|
||
|
|
||
|
fn field_at_mut(&mut self, idx: usize) -> Option<&mut dyn Reflect>;
|
||
|
|
||
|
/// Returns the name of the field at the index. Will only return something if this [`EnumType`]
|
||
|
/// is a `Struct`.
|
||
|
fn field_name_at(&self, idx: usize) -> Option<String>;
|
||
|
|
||
|
fn has_field(&self, name: &str) -> bool;
|
||
|
|
||
|
/// Returns the number of fields inside the variant of the enum.
|
||
|
fn fields_len(&self) -> usize;
|
||
|
|
||
|
/// Returns the number of variants the enum has.
|
||
|
fn variants_len(&self) -> usize;
|
||
|
|
||
|
/// Returns the name of the current enum item that self is.
|
||
|
fn variant_name(&self) -> String;
|
||
|
|
||
|
/// Returns the index of the current enum item that self is.
|
||
|
fn variant_index(&self) -> usize;
|
||
|
|
||
|
/// Returns a boolean indicating if self is an instance of the provided variant.
|
||
|
fn is_variant_name(&self, name: &str) -> bool;
|
||
|
|
||
|
/// Returns the type of the variant that self is an instance of
|
||
|
fn variant_type(&self) -> EnumType;
|
||
|
}
|
||
|
|
||
|
#[cfg(test)]
|
||
|
mod tests {
|
||
|
use lyra_reflect_derive::Reflect;
|
||
|
|
||
|
use super::EnumType;
|
||
|
use crate::{lyra_engine, Reflect, ReflectRef};
|
||
|
|
||
|
#[derive(Clone, Reflect)]
|
||
|
enum TestEnum {
|
||
|
Start,
|
||
|
Middle(u32, u64),
|
||
|
Error { msg: String, code: u32},
|
||
|
}
|
||
|
|
||
|
#[test]
|
||
|
fn unit_variant() {
|
||
|
let test_enum = TestEnum::Start;
|
||
|
let test_enum = Box::new(test_enum) as Box<dyn Reflect>;
|
||
|
|
||
|
if let ReflectRef::Enum(e) = test_enum.reflect_ref() {
|
||
|
assert_eq!(e.variant_type(), EnumType::Unit);
|
||
|
assert_eq!(e.variant_index(), 0);
|
||
|
assert_eq!(e.variants_len(), 3);
|
||
|
assert_eq!(e.fields_len(), 0);
|
||
|
assert_eq!(e.variant_name().to_lowercase(), "start".to_string());
|
||
|
assert!(e.is_variant_name("start"));
|
||
|
} else {
|
||
|
panic!("The reflected reference was not an Enum!");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#[test]
|
||
|
fn struct_variant() {
|
||
|
let test_enum = TestEnum::Error { msg: "sick test".to_string(), code: 420 };
|
||
|
let test_enum = Box::new(test_enum) as Box<dyn Reflect>;
|
||
|
|
||
|
if let ReflectRef::Enum(e) = test_enum.reflect_ref() {
|
||
|
assert_eq!(e.variant_type(), EnumType::Struct);
|
||
|
assert_eq!(e.variant_index(), 2);
|
||
|
assert_eq!(e.variants_len(), 3);
|
||
|
assert_eq!(e.fields_len(), 2);
|
||
|
assert_eq!(e.variant_name().to_lowercase(), "error".to_string());
|
||
|
assert!(e.is_variant_name("error"));
|
||
|
|
||
|
let msg = e.field("msg").unwrap();
|
||
|
let msg = msg.as_any().downcast_ref::<String>().unwrap();
|
||
|
assert_eq!(msg, "sick test");
|
||
|
|
||
|
let code: &dyn Reflect = e.field("code").unwrap();
|
||
|
let code = code.as_any().downcast_ref::<u32>().unwrap();
|
||
|
assert_eq!(*code, 420);
|
||
|
} else {
|
||
|
panic!("The reflected reference was not an Enum!");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#[test]
|
||
|
fn tuple_variant() {
|
||
|
let test_enum = TestEnum::Middle(420, 69);
|
||
|
let test_enum = Box::new(test_enum) as Box<dyn Reflect>;
|
||
|
|
||
|
if let ReflectRef::Enum(e) = test_enum.reflect_ref() {
|
||
|
assert_eq!(e.variant_type(), EnumType::Tuple);
|
||
|
assert_eq!(e.variant_index(), 1);
|
||
|
assert_eq!(e.variants_len(), 3);
|
||
|
assert_eq!(e.fields_len(), 2);
|
||
|
assert_eq!(e.variant_name().to_lowercase(), "middle".to_string());
|
||
|
assert!(e.is_variant_name("middle"));
|
||
|
|
||
|
let msg = e.field("msg");
|
||
|
assert!(msg.is_none());
|
||
|
let code = e.field("code");
|
||
|
assert!(code.is_none());
|
||
|
|
||
|
|
||
|
let a = e.field_at(0).unwrap();
|
||
|
let a = a.as_any().downcast_ref::<u32>().unwrap();
|
||
|
assert_eq!(*a, 420);
|
||
|
|
||
|
let b = e.field_at(1).unwrap();
|
||
|
let b = b.as_any().downcast_ref::<u64>().unwrap();
|
||
|
assert_eq!(*b, 69);
|
||
|
} else {
|
||
|
panic!("The reflected reference was not an Enum!");
|
||
|
}
|
||
|
}
|
||
|
}
|