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; 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; } #[allow(unused_variables)] #[cfg(test)] mod tests { 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; 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; 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::().unwrap(); assert_eq!(msg, "sick test"); let code: &dyn Reflect = e.field("code").unwrap(); let code = code.as_any().downcast_ref::().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; 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::().unwrap(); assert_eq!(*a, 420); let b = e.field_at(1).unwrap(); let b = b.as_any().downcast_ref::().unwrap(); assert_eq!(*b, 69); } else { panic!("The reflected reference was not an Enum!"); } } }