use std::convert::From;
use binding::class;
use binding::global::ValueType;
use binding::util as binding_util;
use result::{Error, Result};
use typed_data::DataTypeWrapper;
use types::{Callback, Value};
use util;
use {AnyObject, Boolean, Class, VerifiedObject};
pub trait Object: From<Value> {
#[inline]
fn value(&self) -> Value;
fn class(&self) -> Class {
let class = class::object_class(self.value());
Class::from(class)
}
fn singleton_class(&self) -> Class {
let class = class::singleton_class(self.value());
Class::from(class)
}
fn get_data<'a, T>(&'a self, wrapper: &'a DataTypeWrapper<T>) -> &mut T {
class::get_data(self.value(), wrapper)
}
fn define<F: Fn(&mut Self)>(&mut self, f: F) -> &Self {
f(self);
self
}
fn define_method<I: Object, O: Object>(&mut self, name: &str, callback: Callback<I, O>) {
class::define_method(self.value(), name, callback);
}
fn define_singleton_method<I: Object, O: Object>(&mut self,
name: &str,
callback: Callback<I, O>) {
class::define_singleton_method(self.value(), name, callback);
}
fn def<I: Object, O: Object>(&mut self, name: &str, callback: Callback<I, O>) {
self.define_method(name, callback);
}
fn def_self<I: Object, O: Object>(&mut self, name: &str, callback: Callback<I, O>) {
self.define_singleton_method(name, callback);
}
fn send(&self, method: &str, arguments: Vec<AnyObject>) -> AnyObject {
let (argc, argv) = util::create_arguments(arguments);
let result = binding_util::call_method(self.value(), method, argc, argv.as_ptr());
AnyObject::from(result)
}
fn respond_to(&self, method: &str) -> bool {
class::respond_to(self.value(), method)
}
fn is_nil(&self) -> bool {
self.value().is_nil()
}
fn to_any_object(&self) -> AnyObject {
AnyObject::from(self.value())
}
fn instance_variable_get(&self, variable: &str) -> AnyObject {
let result = class::instance_variable_get(self.value(), variable);
AnyObject::from(result)
}
fn instance_variable_set<T: Object>(&mut self, variable: &str, value: T) -> AnyObject {
let result = class::instance_variable_set(self.value(), variable, value.value());
AnyObject::from(result)
}
fn is_frozen(&self) -> bool {
let result = class::is_frozen(self.value());
Boolean::from(result).to_bool()
}
fn freeze(&mut self) -> Self {
let result = class::freeze(self.value());
Self::from(result)
}
unsafe fn to<T: Object>(&self) -> T {
T::from(self.value())
}
fn try_convert_to<T: VerifiedObject>(&self) -> Result<T> {
if T::is_correct_type(self) {
let converted_object = unsafe { self.to::<T>() };
Ok(converted_object)
} else {
Err(Error::TypeError(T::error_message().to_string()))
}
}
fn ty(&self) -> ValueType {
self.value().ty()
}
}