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