imag/libimagruby/src/util.rs

102 lines
3.1 KiB
Rust

//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//
use ruru::AnyObject;
pub trait Wrap {
fn wrap(self) -> AnyObject;
}
#[macro_export]
macro_rules! impl_wrap {
($target:ty => $wrapper:path) => {
impl Wrap for $target {
fn wrap(self) -> AnyObject {
Class::from_existing(concat!("R", stringify!($target)))
.wrap_data(self, &*($wrapper))
}
}
}
}
pub trait Unwrap {
type Target;
fn unwrap<'a>(&'a self) -> &'a mut Self::Target;
}
#[macro_export]
macro_rules! impl_unwrap {
($from:ty => $to:ty => $wrapper:path) => {
impl Unwrap for $from {
type Target = $to;
fn unwrap<'a>(&'a self) -> &'a mut $to {
self.get_data(&*($wrapper))
}
}
}
}
#[macro_export]
macro_rules! impl_verified_object {
($objname: ty) => {
impl VerifiedObject for $objname {
fn is_correct_type<T: Object>(object: &T) -> bool {
object.class() == Class::from_existing(stringify!($objname))
}
fn error_message() -> &'static str {
concat!("Not a ", stringify!($objname), " object")
}
}
};
}
/// Helper macro to simplify type checking in the ruby-interfacing functions.
///
/// # Return
///
/// If called with only the object to check, this returns NIL after raising an exception.
/// If called with more arguments, the other things will be returned.
/// E.G.:
///
/// ```ignore
/// let obj1 = typecheck!(obj1); // returns `obj` or raises exception
///
/// // returns `obj` or raises exception and returns AnyObject (Boolean -> false):
/// let obj2 = typecheck!(obj2 or return any Boolean::new(false));
///
/// // returns `obj` or raises excpetion and returns Boolean -> false
/// let obj3 = typecheck!(obj3 or return Boolean::new(false));
/// ```
///
#[macro_export]
macro_rules! typecheck {
($obj: ident) => { typecheck!($obj or return NilClass::new()) };
($obj: ident or return any $els: expr) => { typecheck!($obj or return $els.to_any_object()) };
($obj: ident or return $els: expr) => {
match $obj {
Ok(o) => o,
Err(e) => {
VM::raise(e.to_exception(), e.description());
return $els
},
}
};
}