use std::convert::From;
use crate::{
binding::{class, global::rb_cObject, module},
typed_data::DataTypeWrapper,
types::{Callback, Value, ValueType},
AnyObject, Array, Class, Object, VerifiedObject,
};
#[derive(Debug)]
#[repr(C)]
pub struct Module {
value: Value,
}
impl Module {
pub fn new(name: &str) -> Self {
Self::from(module::define_module(name))
}
pub fn from_existing(name: &str) -> Self {
let object_module = unsafe { rb_cObject };
Self::from(class::const_get(object_module, name))
}
pub fn ancestors(&self) -> Vec<Module> {
let ancestors = Array::from(class::ancestors(self.value()));
ancestors
.into_iter()
.map(|module| unsafe { module.to::<Self>() })
.collect()
}
pub fn get_nested_module(&self, name: &str) -> Self {
Self::from(class::const_get(self.value(), name))
}
pub fn get_nested_class(&self, name: &str) -> Class {
Class::from(class::const_get(self.value(), name))
}
pub fn define_nested_module(&mut self, name: &str) -> Self {
Self::from(module::define_nested_module(self.value(), name))
}
pub fn define_nested_class(&mut self, name: &str, superclass: Option<&Class>) -> Class {
let superclass = Self::superclass_to_value(superclass);
Class::from(class::define_nested_class(self.value(), name, superclass))
}
pub fn define_module_function<I: Object, O: Object>(
&mut self,
name: &str,
callback: Callback<I, O>,
) {
module::define_module_function(self.value(), name, callback);
}
pub fn mod_func<I: Object, O: Object>(&mut self, name: &str, callback: Callback<I, O>) {
self.define_module_function(name, callback);
}
pub fn const_get(&self, name: &str) -> AnyObject {
let value = class::const_get(self.value(), name);
AnyObject::from(value)
}
pub fn const_set<T: Object>(&mut self, name: &str, value: &T) {
class::const_set(self.value(), name, value.value());
}
pub fn include(&self, md: &str) {
module::include_module(self.value(), md);
}
pub fn prepend(&self, md: &str) {
module::prepend_module(self.value(), md);
}
pub fn attr_reader(&mut self, name: &str) {
class::define_attribute(self.value(), name, true, false);
}
pub fn attr_writer(&mut self, name: &str) {
class::define_attribute(self.value(), name, false, true);
}
pub fn attr_accessor(&mut self, name: &str) {
class::define_attribute(self.value(), name, true, true);
}
pub fn wrap_data<T, O: Object>(&self, data: T, wrapper: &dyn DataTypeWrapper<T>) -> O {
let value = class::wrap_data(self.value(), data, wrapper);
O::from(value)
}
fn superclass_to_value(superclass: Option<&Class>) -> Value {
match superclass {
Some(class) => class.value(),
None => unsafe { rb_cObject },
}
}
}
impl From<Value> for Module {
fn from(value: Value) -> Self {
Module { value }
}
}
impl Into<Value> for Module {
fn into(self) -> Value {
self.value
}
}
impl Into<AnyObject> for Module {
fn into(self) -> AnyObject {
AnyObject::from(self.value)
}
}
impl Object for Module {
#[inline]
fn value(&self) -> Value {
self.value
}
}
impl VerifiedObject for Module {
fn is_correct_type<T: Object>(object: &T) -> bool {
object.value().ty() == ValueType::Module
}
fn error_message() -> &'static str {
"Error converting to Module"
}
}
impl PartialEq for Module {
fn eq(&self, other: &Self) -> bool {
self.equals(other)
}
}