lyra-engine/lyra-reflect/src/reflected_enum.rs

138 lines
4.7 KiB
Rust
Raw Normal View History

2023-12-30 23:55:05 +00:00
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!");
}
}
}