artichoke_backend/globals.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
use std::borrow::Cow;
use crate::core::{Globals, Intern};
use crate::error::Error;
use crate::sys;
use crate::value::Value;
use crate::Artichoke;
// TODO: Handle invalid variable names. For now this is delegated to mruby.
// The parser in `spinoso-symbol` can handle this.
impl Globals for Artichoke {
type Value = Value;
type Error = Error;
fn set_global_variable<T>(&mut self, name: T, value: &Self::Value) -> Result<(), Self::Error>
where
T: Into<Cow<'static, [u8]>>,
{
let sym = self.intern_bytes(name.into())?;
unsafe {
self.with_ffi_boundary(|mrb| sys::mrb_gv_set(mrb, sym, value.inner()))?;
}
Ok(())
}
/// Unset global variable pointed to by `name`.
///
/// Unsetting a global variable removes the name from the global storage
/// table. Unset globals resolve to `nil` in the Ruby VM.
///
/// Unsetting a global that is currently unset is a no-op.
///
/// # Errors
///
/// If the name is not a valid global name, an error is returned.
fn unset_global_variable<T>(&mut self, name: T) -> Result<(), Self::Error>
where
T: Into<Cow<'static, [u8]>>,
{
let sym = self.intern_bytes(name.into())?;
let nil = Value::nil();
unsafe {
self.with_ffi_boundary(|mrb| sys::mrb_gv_set(mrb, sym, nil.inner()))?;
}
Ok(())
}
fn get_global_variable<T>(&mut self, name: T) -> Result<Option<Self::Value>, Self::Error>
where
T: Into<Cow<'static, [u8]>>,
{
let sym = self.intern_bytes(name.into())?;
let value = unsafe { self.with_ffi_boundary(|mrb| sys::mrb_gv_get(mrb, sym))? };
// NOTE: This implementation is not compliant with the spec laid out in
// the trait documentation. This implementation always returns `Some(_)`
// even if the global is unset.
Ok(Some(Value::from(value)))
}
}