1pub mod error;
4pub mod registry;
5pub mod reflection;
6pub mod traits;
7
8pub use dynasty_macros::{Class, inherit};
10
11pub use crate::registry::ClassInfo;
13pub use crate::traits::{Class as ClassTrait, Inherits, SafeDowncast};
14#[cfg(feature = "reflection")]
15pub use crate::reflection::{Reflect, ReflectionData};
16
17pub mod prelude {
19 pub use crate::{Class, inherit};
20 pub use crate::traits::{Inherits, SafeDowncast};
21 pub use crate::registry::Registry;
22
23 #[cfg(feature = "reflection")]
24 pub use crate::reflection::Reflect;
25}
26
27#[cfg(test)]
28mod tests {
29 use super::*;
30 use std::any::{Any, TypeId};
31
32 #[derive(Class, Debug)]
34 struct Entity {
35 id: u64,
36 name: String,
37 }
38
39 #[inherit(Entity)]
40 #[derive(Debug)]
41 struct Character {
42 health: f32,
43 level: u32,
44 }
45
46 #[inherit(Character)]
47 #[derive(Debug)]
48 struct Player {
49 experience: u32,
50 }
51
52 #[test]
54 fn test_basic_inheritance() {
55 let entity = Entity {
56 id: 1,
57 name: "Test Entity".to_string(),
58 };
59
60 let character = Character {
61 base: Entity {
62 id: 2,
63 name: "Test Character".to_string(),
64 },
65 health: 100.0,
66 level: 1,
67 };
68
69 assert_eq!(entity.id, 1);
70 assert_eq!(character.base.id, 2);
71 assert_eq!(character.health, 100.0);
72 }
73
74 #[test]
76 fn test_multilevel_inheritance() {
77 let player = Player {
78 base: Character {
79 base: Entity {
80 id: 3,
81 name: "Test Player".to_string(),
82 },
83 health: 100.0,
84 level: 1,
85 },
86 experience: 0,
87 };
88
89 assert_eq!(player.base.base.id, 3);
90 assert_eq!(player.base.health, 100.0);
91 assert_eq!(player.experience, 0);
92 }
93
94 #[test]
96 fn test_class_registry() {
97 let entity_info = Entity::class_info();
98 let character_info = Character::class_info();
99
100 assert_eq!(entity_info.name, "Entity");
101 assert_eq!(character_info.name, "Character");
102 assert!(character_info.parent.is_some());
103 }
104
105 #[test]
107 fn test_type_checking() {
108 let player = Player {
109 base: Character {
110 base: Entity {
111 id: 4,
112 name: "Test Player".to_string(),
113 },
114 health: 100.0,
115 level: 1,
116 },
117 experience: 0,
118 };
119
120 assert_eq!(player.as_any().type_id(), TypeId::of::<Player>());
122 assert_eq!(player.base.as_any().type_id(), TypeId::of::<Character>());
123 assert_eq!(player.base.base.as_any().type_id(), TypeId::of::<Entity>());
124
125 let as_character = player.base.as_any().downcast_ref::<Character>();
127 assert!(as_character.is_some());
128 }
129
130 #[test]
132 fn test_game_patterns() {
133 #[derive(Class)]
134 struct Transform {
135 position: (f32, f32, f32),
136 }
137
138 #[inherit(Entity)]
139 struct GameObject {
140 transform: Transform,
141 }
142
143 let game_object = GameObject {
144 base: Entity {
145 id: 6,
146 name: "Game Object".to_string(),
147 },
148 transform: Transform {
149 position: (0.0, 0.0, 0.0),
150 },
151 };
152
153 assert_eq!(game_object.transform.position, (0.0, 0.0, 0.0));
154 }
155
156 #[cfg(feature = "reflection")]
157 mod reflection_tests {
158 use super::*;
159 use crate::reflection::Reflect;
160
161 impl Reflect for Player {
162 fn get_field(&self, name: &str) -> Option<&dyn Any> {
163 match name {
164 "experience" => Some(&self.experience),
165 _ => None,
166 }
167 }
168
169 fn get_field_mut(&mut self, name: &str) -> Option<&mut dyn Any> {
170 match name {
171 "experience" => Some(&mut self.experience),
172 _ => None,
173 }
174 }
175
176 fn set_field(&mut self, name: &str, value: Box<dyn Any>) -> Result<(), error::DynastyError> {
177 match name {
178 "experience" => {
179 let type_id = value.type_id();
180 match value.downcast::<u32>() {
181 Ok(exp) => {
182 self.experience = *exp;
183 Ok(())
184 }
185 Err(_) => Err(error::DynastyError::TypeMismatch {
186 expected: "u32".to_string(),
187 found: format!("{:?}", type_id),
188 })
189 }
190 }
191 _ => Err(error::DynastyError::FieldNotFound(name.to_string())),
192 }
193 }
194 }
195
196 #[test]
197 fn test_reflection() {
198 let player = Player {
199 base: Character {
200 base: Entity {
201 id: 5,
202 name: "Reflected Player".to_string(),
203 },
204 health: 100.0,
205 level: 1,
206 },
207 experience: 100,
208 };
209
210 if let Some(exp_field) = player.get_field("experience") {
212 if let Some(exp_value) = exp_field.downcast_ref::<u32>() {
213 assert_eq!(*exp_value, 100);
214 } else {
215 panic!("Failed to downcast experience field to u32");
216 }
217 } else {
218 panic!("Failed to get experience field");
219 }
220
221 assert!(player.get_field("nonexistent").is_none());
223 }
224 }
225}