artichoke_backend/extn/core/env/
mruby.rs1use std::ffi::CStr;
4
5use crate::extn::core::artichoke;
6use crate::extn::core::env::{self, trampoline};
7use crate::extn::prelude::*;
8
9const ENVIRON_CSTR: &CStr = c"Environ";
10static ENV_RUBY_SOURCE: &[u8] = include_bytes!("env.rb");
11
12pub fn init(interp: &mut Artichoke) -> InitializeResult<()> {
13 if interp.is_class_defined::<env::Environ>() {
14 return Ok(());
15 }
16
17 let scope = interp
18 .module_spec::<artichoke::Artichoke>()?
19 .map(EnclosingRubyScope::module)
20 .ok_or_else(|| NotDefinedError::module("Artichoke"))?;
21 let spec = class::Spec::new(
22 "Environ",
23 ENVIRON_CSTR,
24 Some(scope),
25 Some(def::box_unbox_free::<env::Environ>),
26 )?;
27 class::Builder::for_spec(interp, &spec)
28 .value_is_rust_object()
29 .add_method("[]", env_element_reference, sys::mrb_args_req(1))?
30 .add_method("[]=", env_element_assignment, sys::mrb_args_req(2))?
31 .add_method("initialize", env_initialize, sys::mrb_args_none())?
32 .add_method("to_h", env_to_h, sys::mrb_args_none())?
33 .define()?;
34 interp.def_class::<env::Environ>(spec)?;
35 interp.eval(ENV_RUBY_SOURCE)?;
36
37 Ok(())
38}
39
40unsafe extern "C-unwind" fn env_initialize(mrb: *mut sys::mrb_state, slf: sys::mrb_value) -> sys::mrb_value {
41 mrb_get_args!(mrb, none);
42 unwrap_interpreter!(mrb, to => guard);
43 let slf = Value::from(slf);
44 let result = trampoline::initialize(&mut guard, slf);
45 match result {
46 Ok(value) => value.inner(),
47 Err(exception) => {
48 unsafe { error::raise(guard, exception) }
50 }
51 }
52}
53
54unsafe extern "C-unwind" fn env_element_reference(mrb: *mut sys::mrb_state, slf: sys::mrb_value) -> sys::mrb_value {
55 let name = mrb_get_args!(mrb, required = 1);
56 unwrap_interpreter!(mrb, to => guard);
57 let obj = Value::from(slf);
58 let name = Value::from(name);
59 let result = trampoline::element_reference(&mut guard, obj, name);
60 match result {
61 Ok(value) => value.inner(),
62 Err(exception) => {
63 unsafe { error::raise(guard, exception) }
65 }
66 }
67}
68
69unsafe extern "C-unwind" fn env_element_assignment(mrb: *mut sys::mrb_state, slf: sys::mrb_value) -> sys::mrb_value {
70 let (name, value) = mrb_get_args!(mrb, required = 2);
71 unwrap_interpreter!(mrb, to => guard);
72 let obj = Value::from(slf);
73 let name = Value::from(name);
74 let value = Value::from(value);
75 let result = trampoline::element_assignment(&mut guard, obj, name, value);
76 match result {
77 Ok(value) => value.inner(),
78 Err(exception) => {
79 unsafe { error::raise(guard, exception) }
81 }
82 }
83}
84
85unsafe extern "C-unwind" fn env_to_h(mrb: *mut sys::mrb_state, slf: sys::mrb_value) -> sys::mrb_value {
86 mrb_get_args!(mrb, none);
87 unwrap_interpreter!(mrb, to => guard);
88 let obj = Value::from(slf);
89 let result = trampoline::to_h(&mut guard, obj);
90 match result {
91 Ok(value) => value.inner(),
92 Err(exception) => {
93 unsafe { error::raise(guard, exception) }
95 }
96 }
97}