1#![no_std]
4#![allow(non_snake_case)]
5
6use core::{marker::PhantomData, ops::{Deref, DerefMut}};
7pub use dynamic_object_derive::*;
8extern crate alloc;
9use alloc::boxed::Box;
10pub mod typing;
11pub use typing::*;
12
13pub trait Dyn {
14
15}
16
17impl<T> Dyn for T {
18
19}
20
21pub trait Class {
23      type Parent: Sized + Class;
24      const NAME: &'static str;
25
26      fn id() -> usize;
27      fn offset() -> isize;
28      fn isa(id: usize) -> bool;
29}
30
31pub struct Object<T: Class, ContainerT = Box<dyn Dyn>> {
35      object: ContainerT,
38      isa: fn(id: usize) -> bool,
39      offset: i16,
40      _marker: PhantomData<T>
41}
42
43impl<T: Class, ContainerT> Object<T, ContainerT> {
44      pub fn new(object: ContainerT) -> Self {
54            Self {
55                  object,
56                  isa: T::isa,
57                  offset: 0,
58                  _marker: PhantomData
59            }
60      }
61
62      pub fn isa<Other: Class>(&self) -> bool {
73            (self.isa)(Other::id())
74      }
75
76      pub fn cast<Cast: Class>(self) -> Object<Cast, ContainerT> {
116            if isSubclassOf::<Cast, T>() {
117                  assert!(self.isa::<Cast>());
118            }
119            let offset = if isSubclassOf::<Cast, T>() {
120                  -typing::offsetOf::<T, Cast>()
121            }
122            else {
123                  typing::offsetOf::<Cast, T>()
124            } as i16;
125            Object {
126                  object: self.object,
127                  isa: self.isa,
128                  _marker: PhantomData,
129                  offset: self.offset + offset
130            }
131      }
132
133      pub fn vtable(&self) -> &ContainerT {
134            &self.object
135      }
136
137      pub fn vtable_mut(&mut self) -> &mut ContainerT {
138            &mut self.object
139      }
140
141      pub fn try_cast<Cast: Class>(self) -> Option<Object<Cast, ContainerT>> {
143            if isSubclassOf::<Cast, T>() {
144                  if !self.isa::<Cast>() {
145                        return None
146                  }
147            }
148            
149            let offset = if isSubclassOf::<Cast, T>() {
150                  -typing::offsetOf::<T, Cast>()
151            }
152            else {
153                  typing::offsetOf::<Cast, T>()
154            } as i16;
155            Some(Object {
156                  object: self.object,
157                  isa: self.isa,
158                  _marker: PhantomData,
159                  offset: self.offset + offset
160            })
161      }
162}
163
164impl<T: Class, Container: Deref> Deref for Object<T, Container> {
165      type Target = T;
166
167      fn deref(&self) -> &Self::Target {
168            let inner = &*self.object as *const Container::Target as *const ();
169            let inner = inner as usize;
170            let inner = inner.wrapping_add(self.offset as usize);
171            let inner = inner as *const T;
172            unsafe {
173                  &*inner
174            }
175      }
176}
177
178impl<T: Class, Container: DerefMut> DerefMut for Object<T, Container> {
179      fn deref_mut(&mut self) -> &mut Self::Target {
180            let inner = &mut *self.object as *mut Container::Target as *mut ();
181            let inner = inner as usize;
182            let inner = inner.wrapping_add(self.offset as usize);
183            let inner = inner as *mut T;
184            unsafe {
185                  &mut *inner
186            }
187      }
188}
189
190impl<T: Class, Container: Clone> Clone for Object<T, Container> {
191      fn clone(&self) -> Self {
192            Self { 
193                  object: self.object.clone(), 
194                  isa: self.isa, 
195                  offset: self.offset, 
196                  _marker: PhantomData
197            }
198      }
199}
200
201impl<T: Class, Container: Copy> Copy for Object<T, Container> {
202      
203}
204
205pub struct DynamicObjectBase;
214
215impl Class for DynamicObjectBase {
216      type Parent = Self;
217      const NAME: &'static str = "dynamic::ObjectBase";
218
219      fn isa(id: usize) -> bool {
220            id == Self::id()
221      }
222      
223      fn offset() -> isize {
224            0
225      }
226
227      fn id() -> usize {
228            Self::id as *const u8 as usize
229      }
230}
231
232#[cfg(test)]
233mod test {
234      #![allow(unused_imports)]
235      #![allow(dead_code)]
236
237      extern crate std;
238      use dynamic_object_derive::*;
239      use crate as dynamic_object;
241      use crate::*;
242      use std::{println, prelude::*};
244
245      trait A {
246
247      }
248
249      #[subclass(DynamicObjectBase)]
250      struct Class {
251            value: u32,
252            foo: u32
253      }
254
255      #[subclass(Class, parent)]
256      struct Derived {
257            field: u32,
258            parent: Class,
259      }
260
261      #[subclass(DynamicObjectBase)]
262      struct BarObject {
263
264      }
265
266      #[subclass(DynamicObjectBase)]
267      struct AnotherObject {
268
269      }
270
271      #[test]
272      fn isa() {
273            let object = Derived { 
274                  parent: Class {
275                        value: 0,
276                        foo: 0
277                  },
278                  field: 0
279            };
280            let object = Object::<Derived>::new(Box::new(object));
281            assert!(object.isa::<DynamicObjectBase>());
282            assert!(!object.isa::<BarObject>());
283      }
284
285      #[test]
286      fn casting() {
287            let object = Derived {
288                  parent: Class {
289                        value: 548389,
290                        foo: 72840548
291                  },
292                  field: 2153746,
293            };
294            
295            let object = Object::<Derived>::new(Box::new(object));
296            assert!(object.field == 2153746);
297            assert!(object.parent.value == 548389);
298            assert!(object.parent.foo == 72840548);
299            
300            let object = object.cast::<Class>();
301            println!("Parent offset: {}", object.offset);
302            println!("After cast: {}", object.value);
303            assert!(object.value == 548389);
304            assert!(object.foo == 72840548);
305            
306            let object = object.cast::<Derived>();
307            assert!(object.field == 2153746);
308            assert!(object.parent.value == 548389);
309            assert!(object.parent.foo == 72840548);
310      }
311}