artichoke_backend/
class_registry.rs1use 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}