# Minutus
[](https://crates.io/crates/minutus)
[](https://docs.rs/minutus)


Heavily inspired by [Magnus](https://github.com/matsadler/magnus).
By minutus, you can easily [embed mruby in Rust](#embed-mruby-in-rust),
and [create mrbgem by Rust](#create-mrbgem-by-rust).
Minutus also provides sensible [type casting](#type-casting),
and you can [define typed functions to mruby values](#define-typed-functions-to-mruby-values)
and [wrap rust structs in mruby objects](#wrap-rust-structs-in-mruby-objects).
## Embed mruby in Rust
Add minutus to your crate's dependencies.
```shell-session
cargo add minutus --features mruby_3_1_0,link_mruby
```
Write code like:
```rust
// src/main.rs
// This enables you to call `some_method` from Rust world.
minutus::define_funcall!{
fn some_method(self, arr: Vec<i64>) -> i64;
}
fn main() {
let runtime = minutus::build_simple_evaluator();
// define `some_method` in mruby world
runtime.evaluate(
"
def some_method(arr)
p arr
arr.reduce(&:+)
end
"
).unwrap();
// capture mruby's main object
let main = runtime.evaluate("self").unwrap();
// call `some_method` on main object from Rust world.
// in / out values are type-casted, according to `define_funcall!` definition
let retval: i64 = main.some_method(vec![1,2,3,4]);
println!("retval is {}", retval);
}
```
Then, you can run your code:
```shell-session
$ cargo run
...
[1, 2, 3, 4]
retval is 10
```
If you want to use custom `build_config.rb` (e.g. for using mrbgems),
you have to write custom `build.rs`
Minutus provides a helper for this purpose. See [examples/custom-mruby](/examples/custom-mruby).
## Create mrbgem by Rust
Install `minutus-mrbgem-template` and initialize mrbgem.
```shell-session
$ cargo install minutus-mrbgem-template
$ minutus-mrbgem-template mruby-example
$ tree mruby-example
mruby-example
├── Cargo.lock
├── Cargo.toml
├── LICENSE
├── README.md
├── Rakefile
├── mrbgem.rake
├── mrblib
│ └── mrb_example.rb
├── mruby-example.gem
├── src
│ ├── dummy.c
│ └── lib.rs
└── test
└── mrb_example.rb
```
Now, you can build and test mrbgem.
```shell-session
$ cd mruby-example && rake test
...
Total: 1456
OK: 1449
KO: 0
Crash: 0
Warning: 0
Skip: 7
Time: 0.06 seconds
```
## Wrap Rust Structs in mruby Objects
You can wrap Rust's struct in mruby objects.
The following example defines `TestMrbgem` class in mruby,
which has class method `new`, and instance methods `distance` and `name_with_prefix`.
```rust
#[minutus::wrap(class_method = "new", method = "distance", method = "name_with_prefix")]
struct TestMrbgem {
x: i64,
y: i64,
name: String,
}
impl TestMrbgem {
#[minutus::class_method]
pub fn new(x: i64, y: i64, name: String) -> Self {
Self { x, y, name }
}
#[minutus::method]
pub fn distance(&self, other: &TestMrbgem) -> f64 {
(((self.x - other.x).pow(2) + (self.y - other.y).pow(2)) as f64).sqrt()
}
#[minutus::method]
pub fn name_with_prefix(&self, prefix: String) -> String {
[prefix, self.name.clone()].join("_")
}
}
```
## Define typed functions to mruby values
Use `define_funcall!` macro.
```rust
minutus::define_funcall! {
fn inspect(self) -> String;
fn concat(self, other: Vec<&str>) -> Vec<String> => "+";
}
fn main() {
let runtime = minutus::build_simple_evaluator();
let mruby_array: minutus::types::MinuValue = runtime.evaluate("['aaa', 'bbb']").unwrap();
assert_eq!("[\"aaa\", \"bbb\"]", mruby_array.inspect());
assert_eq!(vec![String::from("aaa"), String::from("bbb"), String::from("ccc")], mruby_array.concat(vec!["ccc"]));
```
## Type casting
See [minutus/src/types](minutus/src/types) for details.
| `i8`, `i16`, `i32`, `i64`, `isize` | `Integer` |
| `u8`, `u16`, `u32`, `u64`, `usize` | `Integer` |
| `f32`, `f64` | `Float` |
| `String` | `String` |
| `Option<T>` | `T` or `nil` |
| `(T, U)`, `(T, U, V)`, etc | `[T, U]`, `[T, U, V]`, etc |
| `Vec<T>` | `Array` |
| `std::collections::HashMap<T, U>` | `Hash` |
| `minutus::types::RSymbol` | `Symbol` |
| `bool` | any object |
| `MrbData` (structs marked by `minutus::wrap`) | corresponding class |
Any value in mruby can be cast to Rust's `bool`.
Rust's `bool` cast to mruby's `true` or `false`.
## Supported mruby versions
Currently, only [3.1.0](https://github.com/mruby/mruby/releases/tag/3.1.0) is supported.
You can use `mruby_master` feature, but it is not guaranteed to work.
## Naming
Minutus is an antonym of [Magnus](https://github.com/matsadler/magnus),
which means _small_.