artichoke_backend/
constant.rs

1use std::ffi::CString;
2
3use crate::Artichoke;
4use crate::core::DefineConstant;
5use crate::def::{ConstantNameError, NotDefinedError};
6use crate::error::Error;
7use crate::ffi::InterpreterExtractError;
8use crate::sys;
9use crate::value::Value;
10
11impl DefineConstant for Artichoke {
12    type Value = Value;
13
14    type Error = Error;
15
16    fn define_global_constant(&mut self, constant: &str, value: Self::Value) -> Result<(), Self::Error> {
17        let Ok(name) = CString::new(constant) else {
18            return Err(ConstantNameError::from(String::from(constant)).into());
19        };
20        unsafe {
21            self.with_ffi_boundary(|mrb| sys::mrb_define_global_const(mrb, name.as_ptr(), value.inner()))?;
22        }
23        Ok(())
24    }
25
26    fn define_class_constant<T>(&mut self, constant: &str, value: Self::Value) -> Result<(), Self::Error>
27    where
28        T: 'static,
29    {
30        let Ok(name) = CString::new(constant) else {
31            return Err(ConstantNameError::from(String::from(constant)).into());
32        };
33        let state = self.state.as_deref_mut().ok_or_else(InterpreterExtractError::new)?;
34        let spec = state
35            .classes
36            .get::<T>()
37            .ok_or_else(|| NotDefinedError::class_constant(String::from(constant)))?;
38        let rclass = spec.rclass();
39
40        let rclass = unsafe { self.with_ffi_boundary(|mrb| rclass.resolve(mrb))? };
41        let Some(mut rclass) = rclass else {
42            return Err(NotDefinedError::class_constant(String::from(constant)).into());
43        };
44        unsafe {
45            self.with_ffi_boundary(|mrb| {
46                sys::mrb_define_const(mrb, rclass.as_mut(), name.as_ptr(), value.inner());
47            })?;
48        }
49        Ok(())
50    }
51
52    fn define_module_constant<T>(&mut self, constant: &str, value: Self::Value) -> Result<(), Self::Error>
53    where
54        T: 'static,
55    {
56        let Ok(name) = CString::new(constant) else {
57            return Err(ConstantNameError::from(String::from(constant)).into());
58        };
59        let state = self.state.as_deref_mut().ok_or_else(InterpreterExtractError::new)?;
60        let spec = state
61            .modules
62            .get::<T>()
63            .ok_or_else(|| NotDefinedError::module_constant(String::from(constant)))?;
64        let rclass = spec.rclass();
65
66        let rclass = unsafe { self.with_ffi_boundary(|mrb| rclass.resolve(mrb))? };
67        let Some(mut rclass) = rclass else {
68            return Err(NotDefinedError::module_constant(String::from(constant)).into());
69        };
70        unsafe {
71            self.with_ffi_boundary(|mrb| {
72                sys::mrb_define_const(mrb, rclass.as_mut(), name.as_ptr(), value.inner());
73            })?;
74        }
75        Ok(())
76    }
77}