1use std::any::Any;
2use std::cell::{Ref, RefCell, RefMut};
3use std::fmt::Debug;
4use std::ops::Deref;
5use std::rc::Rc;
6
7use crate::libapi::Class;
8use crate::sym::Symbol;
9use crate::traits::Dispatchable;
10
11pub trait Obj: Class + Debug + Dispatchable {
12 fn as_any(&self) -> &dyn Any;
13 fn as_mut_any(&mut self) -> &mut dyn Any;
14 fn equals_obj(&self, _: &dyn Obj) -> bool;
15}
16
17impl<T: 'static + PartialEq + Eq + Class + Debug> Obj for T {
18 fn as_any(&self) -> &dyn Any {
19 self
20 }
21
22 fn as_mut_any(&mut self) -> &mut dyn Any {
23 self
24 }
25
26 fn equals_obj(&self, other: &dyn Obj) -> bool {
27 other.as_any().downcast_ref::<T>() == Some(self)
28 }
29}
30
31impl<T: Obj> Dispatchable for T {
32 fn lookup_symbol(&self, name: &str) -> Option<Symbol> {
33 self.get(name).copied()
34 }
35}
36
37#[derive(Debug, Clone)]
38pub struct ObjRef {
39 inner: Rc<RefCell<dyn Obj>>,
40}
41
42impl From<Rc<RefCell<dyn Obj>>> for ObjRef {
43 fn from(obj: Rc<RefCell<dyn Obj>>) -> Self {
44 Self { inner: obj }
45 }
46}
47
48impl<T: 'static + Obj> From<T> for ObjRef {
49 fn from(obj: T) -> Self {
50 Self {
51 inner: Rc::new(RefCell::new(obj)),
52 }
53 }
54}
55
56impl Eq for ObjRef {}
57impl PartialEq for ObjRef {
58 fn eq(&self, other: &ObjRef) -> bool {
59 self.inner.borrow().equals_obj(other.inner.borrow().deref())
60 }
61}
62
63impl Dispatchable for ObjRef {
64 fn lookup_symbol(&self, name: &str) -> Option<Symbol> {
65 self.inner.borrow().lookup_symbol(name)
66 }
67}
68
69impl ObjRef {
70 pub fn borrow(&self) -> Ref<'_, dyn Obj> {
71 self.inner.borrow()
72 }
73
74 pub fn borrow_mut(&self) -> RefMut<'_, dyn Obj> {
75 self.inner.borrow_mut()
76 }
77}