1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
//! Minutus is a library which enables you to 1) embed mruby into your Rust project, and 2) create mrbgem in Rust.

pub mod data;
pub mod types;

/// Define methods for [MrbValue][`types::MrbValue`].
///
/// # Examples
///
/// ```
/// minutus::define_funcall! {
///     fn inspect(self) -> String;
///     fn concat(self, other: Vec<&str>) -> Vec<String> => "+";
/// }
///
/// fn main() {
///     let runtime = minutus::Evaluator::build();
///     let mruby_array: minutus::types::MrbValue = runtime.evaluate("['aaa', 'bbb']").unwrap();
///     assert_eq!("[\"aaa\", \"bbb\"]", mruby_array.inspect().unwrap());
///     assert_eq!(vec![String::from("aaa"), String::from("bbb"), String::from("ccc")], mruby_array.concat(vec!["ccc"]).unwrap());
/// }
/// ```
///
/// By giving target type for `define_funcall!`, methods are defined only on given type.
///
/// ```
/// use minutus::mruby::*;
/// use minutus::types::*;
/// use minutus::*;
///
/// struct CustomNumeric(MrbValue);
/// impl MrbValueLike for CustomNumeric {
///     fn mrb(&self) -> *mut minu_state {
///         self.0.mrb()
///     }
///
///     fn val(&self) -> minu_value {
///         self.0.val()
///     }
/// }
/// impl TryFromMrb for CustomNumeric {
///     fn try_from_mrb(value: MrbValue) -> MrbResult<Self> {
///         // You should check the value in reality!
///         Ok(CustomNumeric(value))
///     }
/// }
/// impl TryIntoMrb for CustomNumeric {
///     fn try_into_mrb(self, _mrb: *mut minu_state) -> MrbResult<MrbValue> {
///         Ok(self.0)
///     }
/// }
///
/// // MrbValueLike, TryFromMrb and TryIntoMrb must be implemeted for CustomNumeric
/// define_funcall! {
///   CustomNumeric;
///   fn plus(&self, other: CustomNumeric) -> CustomNumeric => "+";
///   fn inspect(&self) -> String;
/// }
///
/// fn main() {
///     let runtime = Evaluator::build();
///     let num_1 = runtime.eval_to::<CustomNumeric>("123").unwrap();
///     let num_2 = runtime.eval_to::<CustomNumeric>("246").unwrap();
///     let result = num_1.plus(num_2).unwrap().inspect().unwrap();
///     assert_eq!("369", result);
///
///     let mrb_value = runtime.evaluate("111").unwrap();
///     // This does not compile.
///     // mrb_value.plus(num_2)
/// }
/// ```
pub use minutus_macros::define_funcall;

/// Define methods for [DataPtr][`data::DataPtr`].
///
/// # Examples
///
/// ```
/// extern crate minutus;
///
/// #[minutus::wrap(class_method = "new", method = "distance")]
/// struct Point {
///     x: i64,
///     y: i64,
/// }
///
/// impl Point {
///     #[minutus::class_method]
///     pub fn new(x: i64, y: i64) -> Self {
///         Self { x, y }
///     }
///
///     #[minutus::method]
///     pub fn distance(&self, other: &Point) -> f64 {
///         (((self.x - other.x).pow(2) + (self.y - other.y).pow(2)) as f64).sqrt()
///     }
/// }
///
/// minutus::extern_methods! {
///     Point;
///     fn name() -> String; // class method
///     fn inspect(self) -> String; // instance method
/// }
///
/// fn main() {
///     use minutus::types::TryFromMrb; // for using `Point::try_from_mrb`
///
///     let runtime = minutus::Evaluator::build();
///     Point::define_class_on_mrb(runtime.mrb());
///
///     let point = Point::try_from_mrb(runtime.evaluate("Point.new(1,2)").unwrap()).unwrap();
///     // evaluates `point.inspect` in mruby world, and returns its value
///     point.inspect(); // => "#<Point:0x140009fb0>"
///
///     // evaluates `Point.name` in mruby world, and returns its value
///     // note: class methods requires `mrb` as argument
///     Point::name(runtime.mrb()); // => "Point"
/// }
/// ```
pub use minutus_macros::extern_methods;

/// Macro that generates [RData](https://mruby.org/docs/api/headers/mruby_2Fdata.h.html) definition for Rust types.
///
/// # Example
///
/// See also [`data`] and [`extern_methods!`]
///
/// ```
/// extern crate minutus;
///
/// // You can repeat `class_method` and `method` any times.
/// #[minutus::wrap(class_method = "new", method = "distance")]
/// struct Point {
///     x: i64,
///     y: i64,
/// }
///
/// impl Point {
///     #[minutus::class_method]
///     pub fn new(x: i64, y: i64) -> Self {
///         Self { x, y }
///     }
///
///     #[minutus::method]
///     pub fn distance(&self, other: &Point) -> f64 {
///         (((self.x - other.x).pow(2) + (self.y - other.y).pow(2)) as f64).sqrt()
///     }
/// }
///
/// fn main() {
///     use minutus::types::TryFromMrb; // for using `Point::try_from_mrb`
///
///     let runtime = minutus::Evaluator::build();
///
///     // register class in mruby
///     Point::define_class_on_mrb(runtime.mrb());
///
///     runtime.evaluate(
///       "
///         p1 = Point.new(1,1)
///         p2 = Point.new(2,2)
///         p p1.distance(p2) # => prints 1.41421356
///       "
///     ).unwrap();
/// }
/// ```
pub use minutus_macros::wrap;

/// See [`wrap`]
pub use minutus_macros::{class_method, method, MrbData};

mod evaluator;
pub use evaluator::*;
pub mod mruby;

pub use minutus_mruby_build_utils::MRubyManager;