use builder;
use ffi;
use util;
use libc;
use std::fmt;
#[derive(Copy,Clone)]
pub struct Value(pub ffi::VALUE);
impl Value
{
pub fn nil() -> Self {
Self::from(ffi::Qnil)
}
pub fn symbol(name: &str) -> Self {
Self::from(unsafe { ffi::rb_id2sym(Self::intern(name)) })
}
pub fn string(s: &str) -> Self {
Self::from(unsafe { ffi::rb_id2str(Self::intern(s)) })
}
pub fn fixnum(v: i64) -> Self {
Self::from(ffi::INT2FIX(v as _))
}
pub fn float(v: f64) -> Self {
Self::from(unsafe { ffi::rb_float_new(v as libc::c_double) })
}
pub fn to_sym(&self) -> Value {
Self::from(unsafe { ffi::rb_to_symbol(self.0) })
}
pub fn to_i64(&self) -> i64 {
unsafe { ffi::rb_num2long(self.0) as i64 }
}
pub fn to_u64(&self) -> u64 {
unsafe { ffi::rb_num2ulong(self.0) as u64 }
}
pub fn to_f64(&self) -> f64 {
unsafe { ffi::rb_num2dbl(self.0) as f64 }
}
pub fn class(&self) -> Value {
Self::from(unsafe { ffi::rb_class_of(self.0) })
}
pub fn nested_class<S>(self, name: S) -> builder::Class
where S: Into<String> {
builder::Class::new_under(name, Some(self))
}
pub fn nested_module<S>(self, name: S) -> builder::Module
where S: Into<String> {
builder::Module::new_under(name, Some(self))
}
pub fn display_string(&self) -> String {
self.call_no_args("to_s").as_string().expect("Object#to_s did not return a String")
}
pub fn inspect_string(&self) -> String {
self.call_no_args("inspect").as_string().expect("Object#inspect did not return a String")
}
pub fn class_name(&self) -> String {
unsafe { util::string(ffi::rb_obj_classname(self.0)) }
}
pub fn is_nil(&self) -> bool { self.0 == ffi::Qnil }
pub fn is_string(&self) -> bool { ffi::TYPE_P(self.0, ffi::T_STRING) }
pub fn is_fixnum(&self) -> bool { ffi::TYPE_P(self.0, ffi::T_FIXNUM) }
pub fn is_symbol(&self) -> bool { ffi::TYPE_P(self.0, ffi::T_SYMBOL) }
pub fn is_float(&self) -> bool { ffi::TYPE_P(self.0, ffi::T_FLOAT) }
pub fn is_object(&self) -> bool { ffi::TYPE_P(self.0, ffi::T_OBJECT) }
pub fn is_equal_to(&self, other: Self) -> Self {
Self::from(unsafe { ffi::rb_equal(self.0, other.0) })
}
pub fn as_string(&self) -> Option<String> {
if self.is_string() {
let c_str = unsafe { ffi::rb_string_value_cstr(&self.0 as *const _) };
Some(util::string(c_str))
} else {
None
}
}
pub fn call_no_args(&self, method_name: &str) -> Self {
Self::from(unsafe { ffi::rb_funcall(self.0, Self::intern(method_name), 0) })
}
pub fn send(&self, method_name: &str, args: &[Self]) -> Self {
Self::from(unsafe {
ffi::rb_funcallv(
self.0,
Self::intern(method_name),
args.len() as libc::c_int,
args.as_ptr() as *const _,
)
})
}
pub fn get_ivar(&self, name: &str) -> Self {
Self::from(unsafe { ffi::rb_iv_get(self.0, util::c_string(name).as_ptr()) })
}
pub fn set_ivar(&self, name: &str, value: Self) -> Self {
Self::from(unsafe { ffi::rb_iv_set(self.0, util::c_string(name).as_ptr(), value.0) })
}
fn intern(s: &str) -> ffi::ID {
unsafe { ffi::rb_intern(util::c_string(s).as_ptr()) }
}
}
impl fmt::Display for Value
{
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
self.display_string().fmt(fmt)
}
}
impl fmt::Debug for Value
{
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
self.display_string().fmt(fmt)
}
}
impl From<ffi::VALUE> for Value
{
fn from(value: ffi::VALUE) -> Value {
Value(value)
}
}