1extern crate plugger_core;
2extern crate rurust;
3extern crate libc;
4
5pub use rurust::Value as Value;
6
7pub mod shims;
9
10#[doc(hidden)]
12pub use self::marshall::Marshall;
13
14mod marshall;
15
16const RUBY_SUPPORT: &'static str = include_str!("../support/ruby.rb");
18const PLUGGER_BASE_CLASS: &'static str = "PluggerObject";
20
21use plugger_core::Pluggable;
22
23pub extern fn do_something() {
24 println!("do_something");
25}
26
27#[derive(Debug)]
28pub enum ErrorKind
29{
30 Ruby(rurust::ErrorKind),
31}
32
33pub struct Ruby
34{
35 pub vm: rurust::VM,
36}
37
38impl Ruby
39{
40 pub fn new() -> Result<Self, ErrorKind> {
41 match rurust::VM::new() {
42 Ok(vm) => {
43 let mut ruby = Ruby { vm: vm };
44 ruby.eval(RUBY_SUPPORT).expect("the support module crashed");
45
46 Ok(ruby)
47 }
48 Err(e) => return Err(ErrorKind::Ruby(e)),
49 }
50 }
51
52 pub fn plug<P>(&mut self, name: &str, object: &mut P) where P: Pluggable {
53 let base_class = self.vm.eval(PLUGGER_BASE_CLASS).expect("could not find the plugger base class");
54
55 let class_builder = object.methods().iter().fold(self.vm.class(object.name()).extend(base_class), |class, method| {
56 let ptr = method.marshall("ruby") as usize;
57 let ptr_value = self.vm.eval(&format!("{}", ptr)).unwrap();
58
59 let name = format!("{}_internal", method.name);
60
61 if method.is_static {
62 class.singleton_method(name, shims::ruby_singleton_method as *mut _, -1)
63 } else {
64 class.method(name, shims::ruby_method as *mut _, -1)
65 }.constant(method.name.to_uppercase(), ptr_value)
66 });
67
68 class_builder.build();
71 let ptr = object as *mut _ as usize;
72
73 let constant_name = name.to_uppercase();
74
75 let ruby_val = self.vm.eval(&format!("{}.new({})", object.name(), ptr)).unwrap();
76 self.vm.set_global_const(&constant_name, ruby_val);
77
78 println!("Plugging in {} {}", object.name(), constant_name);
79 }
80
81 pub fn eval(&mut self, code: &str) -> Result<String, ErrorKind> {
82 match self.vm.eval(code) {
83 Ok(val) => Ok(val.inspect_string()),
84 Err(e) => Err(ErrorKind::Ruby(e)),
85 }
86 }
87}
88