rutie/class/
rproc.rs

1use std::convert::From;
2
3use crate::{
4    binding::rproc, types::Value, util, AnyObject, Boolean, Class, Object, VerifiedObject,
5};
6
7/// `Proc` (works with `Lambda` as well)
8#[derive(Debug)]
9#[repr(C)]
10pub struct Proc {
11    value: Value,
12}
13
14impl Proc {
15    /// Calls a proc with given arguments
16    ///
17    /// # Examples
18    ///
19    /// ```no_run
20    /// #[macro_use]
21    /// extern crate rutie;
22    ///
23    /// use rutie::{Class, Object, Proc, RString};
24    ///
25    /// class!(Greeter);
26    ///
27    /// methods!(
28    ///     Greeter,
29    ///     rtself,
30    ///
31    ///     fn greet_rust_with(greeting_template: Proc) -> RString {
32    ///         let name = RString::new_utf8("Rust").to_any_object();
33    ///         let rendered_template = greeting_template.unwrap().call(&[name]);
34    ///
35    ///         rendered_template.try_convert_to::<RString>().unwrap()
36    ///     }
37    /// );
38    ///
39    /// fn main() {
40    ///     Class::new("Greeter", None).define(|klass| {
41    ///         klass.def_self("greet_rust_with", greet_rust_with);
42    ///     });
43    /// }
44    /// ```
45    ///
46    /// Ruby:
47    ///
48    /// ```ruby
49    /// class Greeter
50    ///   def self.greet_rust_with(greeting_template)
51    ///     greeting_template.call('Rust')
52    ///   end
53    /// end
54    ///
55    /// greeting_template = -> (name) { "Hello, #{name}!" }
56    ///
57    /// Greeter.greet_rust_with(greeting_template) # => "Hello, Rust!"
58    /// ```
59    pub fn call(&self, arguments: &[AnyObject]) -> AnyObject {
60        let arguments = util::arguments_to_values(arguments);
61        let result = rproc::call(self.value(), &arguments);
62
63        AnyObject::from(result)
64    }
65
66    /// Check if Proc is a lambda
67    ///
68    /// # Examples
69    ///
70    /// ```
71    /// use rutie::{Object, Proc, VM, VerifiedObject};
72    /// # VM::init();
73    ///
74    /// let procish = VM::eval("lambda {|a,b| a + b }").unwrap();
75    ///
76    /// assert!(Proc::is_correct_type(&procish), "not Proc!");
77    /// ```
78    ///
79    /// Ruby:
80    ///
81    /// ```ruby
82    /// procish = lambda {|a,b| a + b }
83    ///
84    /// procish.lambda? # => true
85    /// ```
86    pub fn is_lambda(&self) -> bool {
87        Boolean::from(unsafe { self.send("lambda?", &[]) }.value()).to_bool()
88    }
89}
90
91impl From<Value> for Proc {
92    fn from(value: Value) -> Self {
93        Proc { value }
94    }
95}
96
97impl Into<Value> for Proc {
98    fn into(self) -> Value {
99        self.value
100    }
101}
102
103impl Into<AnyObject> for Proc {
104    fn into(self) -> AnyObject {
105        AnyObject::from(self.value)
106    }
107}
108
109impl Object for Proc {
110    #[inline]
111    fn value(&self) -> Value {
112        self.value
113    }
114}
115
116impl VerifiedObject for Proc {
117    fn is_correct_type<T: Object>(object: &T) -> bool {
118        Class::from_existing("Proc").case_equals(object)
119    }
120
121    fn error_message() -> &'static str {
122        "Error converting to Proc"
123    }
124}
125
126impl PartialEq for Proc {
127    fn eq(&self, other: &Self) -> bool {
128        self.equals(other)
129    }
130}