artichoke_backend/
class_registry.rs

1use std::any::Any;
2
3use crate::Artichoke;
4use crate::class;
5use crate::core::ClassRegistry;
6use crate::error::Error;
7use crate::ffi::InterpreterExtractError;
8use crate::sys;
9use crate::value::Value;
10
11impl ClassRegistry for Artichoke {
12    type Value = Value;
13    type Error = Error;
14    type Spec = class::Spec;
15
16    fn def_class<T>(&mut self, spec: Self::Spec) -> Result<(), Self::Error>
17    where
18        T: Any,
19    {
20        let state = self.state.as_deref_mut().ok_or_else(InterpreterExtractError::new)?;
21        state.classes.insert::<T>(Box::new(spec));
22        Ok(())
23    }
24
25    fn class_spec<T>(&self) -> Result<Option<&Self::Spec>, Self::Error>
26    where
27        T: Any,
28    {
29        let state = self.state.as_deref().ok_or_else(InterpreterExtractError::new)?;
30        let spec = state.classes.get::<T>();
31        Ok(spec)
32    }
33
34    fn class_of<T>(&mut self) -> Result<Option<Self::Value>, Self::Error>
35    where
36        T: Any,
37    {
38        let state = self.state.as_deref().ok_or_else(InterpreterExtractError::new)?;
39        let spec = state.classes.get::<T>();
40        let Some(spec) = spec else {
41            return Ok(None);
42        };
43        let rclass = spec.rclass();
44        let value_class = unsafe {
45            self.with_ffi_boundary(|mrb| {
46                if let Some(mut rclass) = rclass.resolve(mrb) {
47                    let value_class = sys::mrb_sys_class_value(rclass.as_mut());
48                    Some(Value::from(value_class))
49                } else {
50                    None
51                }
52            })?
53        };
54        Ok(value_class)
55    }
56
57    fn new_instance<T>(&mut self, args: &[Self::Value]) -> Result<Option<Self::Value>, Self::Error>
58    where
59        T: Any,
60    {
61        let state = self.state.as_deref().ok_or_else(InterpreterExtractError::new)?;
62        let spec = state.classes.get::<T>();
63        let Some(spec) = spec else {
64            return Ok(None);
65        };
66        let rclass = spec.rclass();
67        let args = args.iter().map(Value::inner).collect::<Vec<_>>();
68        let Ok(arglen) = sys::mrb_int::try_from(args.len()) else {
69            return Ok(None);
70        };
71        let instance = unsafe {
72            self.with_ffi_boundary(|mrb| {
73                if let Some(mut rclass) = rclass.resolve(mrb) {
74                    let value = sys::mrb_obj_new(mrb, rclass.as_mut(), arglen, args.as_ptr());
75                    Some(Value::from(value))
76                } else {
77                    None
78                }
79            })?
80        };
81
82        Ok(instance)
83    }
84}