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}