From 0db045ab14db18cb98275296d1f8b90233aa824e Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Wed, 18 Jan 2017 10:42:12 +0100 Subject: Initialize imag-ruby --- Cargo.toml | 1 + imag-ruby/Cargo.toml | 30 ++++++++++++++++++++++++++++++ imag-ruby/src/lib.rs | 26 ++++++++++++++++++++++++++ 3 files changed, 57 insertions(+) create mode 100644 imag-ruby/Cargo.toml create mode 100644 imag-ruby/src/lib.rs diff --git a/Cargo.toml b/Cargo.toml index b12e8164..2a64e19a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,6 +36,7 @@ members = [ "libimagnotes", "libimagref", "libimagrt", + "libimagruby", "libimagstore", "libimagstorestdhook", "libimagtimeui", diff --git a/imag-ruby/Cargo.toml b/imag-ruby/Cargo.toml new file mode 100644 index 00000000..fa1123e0 --- /dev/null +++ b/imag-ruby/Cargo.toml @@ -0,0 +1,30 @@ +[package] +name = "imag-ruby" +version = "0.1.0" +authors = ["Matthias Beyer "] + +description = "Library for the imag core distribution" + +keywords = ["imag", "PIM", "personal", "information", "management"] +readme = "../README.md" +license = "LGPL-2.1" + +documentation = "https://matthiasbeyer.github.io/imag/imag_documentation/index.html" +repository = "https://github.com/matthiasbeyer/imag" +homepage = "http://imag-pim.org" + +[dependencies] +ruru = "0.9" + +[dependencies.libimagerror] +path = "../libimagerror" + +[dependencies.libimagrt] +path = "../libimagrt" + +[dependencies.libimagstore] +path = "../libimagstore" + +[dependencies.libimagutil] +path = "../libimagutil" + diff --git a/imag-ruby/src/lib.rs b/imag-ruby/src/lib.rs new file mode 100644 index 00000000..63ec2fa0 --- /dev/null +++ b/imag-ruby/src/lib.rs @@ -0,0 +1,26 @@ +// +// imag - the personal information management suite for the commandline +// Copyright (C) 2015, 2016 Matthias Beyer and contributors +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; version +// 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// + +#[macro_use] extern crate ruru; + +#[macro_use] extern crate libimagerror; +extern crate libimagstore; +extern crate libimagrt; +#[macro_use] extern crate libimagutil; + -- cgit v1.2.3 From db94e2f1f73fd70aeaeda41b8c45a0a4fc035fda Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Wed, 18 Jan 2017 15:33:57 +0100 Subject: Add StoreId interfacing code --- imag-ruby/Cargo.toml | 2 + imag-ruby/src/lib.rs | 3 ++ imag-ruby/src/store.rs | 141 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 146 insertions(+) create mode 100644 imag-ruby/src/store.rs diff --git a/imag-ruby/Cargo.toml b/imag-ruby/Cargo.toml index fa1123e0..f307f28d 100644 --- a/imag-ruby/Cargo.toml +++ b/imag-ruby/Cargo.toml @@ -15,6 +15,8 @@ homepage = "http://imag-pim.org" [dependencies] ruru = "0.9" +lazy_static = "0.2" +log = "0.3" [dependencies.libimagerror] path = "../libimagerror" diff --git a/imag-ruby/src/lib.rs b/imag-ruby/src/lib.rs index 63ec2fa0..fd2f8d69 100644 --- a/imag-ruby/src/lib.rs +++ b/imag-ruby/src/lib.rs @@ -18,9 +18,12 @@ // #[macro_use] extern crate ruru; +#[macro_use] extern crate lazy_static; +#[macro_use] extern crate log; #[macro_use] extern crate libimagerror; extern crate libimagstore; extern crate libimagrt; #[macro_use] extern crate libimagutil; +pub mod store; diff --git a/imag-ruby/src/store.rs b/imag-ruby/src/store.rs new file mode 100644 index 00000000..04e24bfe --- /dev/null +++ b/imag-ruby/src/store.rs @@ -0,0 +1,141 @@ +// +// imag - the personal information management suite for the commandline +// Copyright (C) 2015, 2016 Matthias Beyer and contributors +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; version +// 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// + +pub mod storeid { + use std::path::PathBuf; + + use ruru::{Class, Object, AnyObject, Boolean, RString, NilClass}; + + use libimagstore::storeid::StoreId; + + wrappable_struct!(StoreId, StoreIdWrapper, STOREID_WRAPPER); + class!(RStoreId); + + methods!( + RStoreId, + itself, + + fn r_storeid_new(base: RString, id: RString) -> AnyObject { + let base = match base.map(|b| b.to_string()).map(PathBuf::from) { + Ok(base) => base, + Err(e) => { + error!("Building StoreId object failed: {:?}", e); + return AnyObject::from(NilClass::new().value()); + }, + }; + + let id = match id.map(|id| id.to_string()).map(PathBuf::from) { + Ok(id) => id, + Err(e) => { + error!("Building StoreId object failed: {:?}", e); + return AnyObject::from(NilClass::new().value()); + }, + }; + + match StoreId::new(Some(base), id) { + Ok(sid) => Class::from_existing("RStoreId").wrap_data(sid, &*STOREID_WRAPPER), + Err(e) => { + error!("Building StoreId object failed: {:?}", e); + return AnyObject::from(NilClass::new().value()); + }, + } + } + + fn r_storeid_new_baseless(id: RString) -> AnyObject { + let id = match id.map(|id| id.to_string()).map(PathBuf::from) { + Ok(id) => id, + Err(e) => { + error!("Building StoreId object failed: {:?}", e); + return AnyObject::from(NilClass::new().value()); + }, + }; + + match StoreId::new(None, id) { + Ok(sid) => Class::from_existing("RStoreId").wrap_data(sid, &*STOREID_WRAPPER), + Err(e) => { + error!("Building StoreId object failed: {:?}", e); + return AnyObject::from(NilClass::new().value()); + }, + } + } + + fn r_storeid_without_base() -> RStoreId { + let withoutbase : StoreId = itself.get_data(&*STOREID_WRAPPER).clone().without_base(); + Class::from_existing("RStoreId").wrap_data(withoutbase, &*STOREID_WRAPPER) + } + + fn r_storeid_with_base(base: RString) -> AnyObject { + let base : PathBuf = match base.map(|b| b.to_string()).map(PathBuf::from) { + Ok(pb) => pb, + Err(e) => { + error!("Error: {:?}", e); + return AnyObject::from(NilClass::new().value()); + }, + }; + let withoutbase : StoreId = itself.get_data(&*STOREID_WRAPPER).clone().with_base(base); + Class::from_existing("RStoreId").wrap_data(withoutbase, &*STOREID_WRAPPER) + } + + fn r_storeid_into_pathbuf() -> AnyObject { + itself.get_data(&*STOREID_WRAPPER) + .clone() + .into_pathbuf() + .map(|pb| pb.to_str().map(String::from).unwrap()) + .as_ref() + .map(|s| AnyObject::from(RString::new(s).value())) + .unwrap_or(AnyObject::from(NilClass::new().value())) + } + + fn r_storeid_exists() -> Boolean { + Boolean::new(itself.get_data(&*STOREID_WRAPPER).exists()) + } + + fn r_storeid_to_str() -> AnyObject { + itself.get_data(&*STOREID_WRAPPER) + .to_str() + .as_ref() + .map(|s| AnyObject::from(RString::new(s).value())) + .unwrap_or(AnyObject::from(NilClass::new().value())) + } + + fn r_storeid_local() -> RString { + let local = itself.get_data(&*STOREID_WRAPPER).local(); + let local = local.to_str().unwrap(); + RString::new(local) + } + + ); + + pub fn setup() -> Class { + let mut class = Class::new("RStoreId", None); + class.define(|itself| { + itself.def_self("new" , r_storeid_new); + itself.def_self("new_baseless" , r_storeid_new_baseless); + + itself.def("without_base" , r_storeid_without_base); + itself.def("with_base" , r_storeid_with_base); + itself.def("into_pathbuf" , r_storeid_into_pathbuf); + itself.def("exists" , r_storeid_exists); + itself.def("to_str" , r_storeid_to_str); + itself.def("local" , r_storeid_local); + }); + class + } + +} -- cgit v1.2.3 From 8324159bc4726829440c598fc04d2b7e74b261ef Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Wed, 18 Jan 2017 19:59:18 +0100 Subject: Add readme file for imag-ruby --- imag-ruby/README.md | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 imag-ruby/README.md diff --git a/imag-ruby/README.md b/imag-ruby/README.md new file mode 100644 index 00000000..92939c35 --- /dev/null +++ b/imag-ruby/README.md @@ -0,0 +1,36 @@ +# imag-ruby + +A Ruby gem for scripting imag modules. + +This crate contains both the Rust bindings for imag using `ruru` and a bunch of +wrapper code for the actual `imag` gem. + +## Why another layer of indirection? + +As "ruru" does not yet support modules, which is sad btw, we would end up with +functions for all the things. + +E.G.: `imag_runtime_setup()` instead of `IMAG::Runtime::setup()` + +I want to add a Ruby gem to wrap these things. +So basically a piece of ruby which uses `imag.rb` (the Rust gem) to build +`imag` as a gem which then exports a fine module system. + +## Ideas for module system: + +```text +IMAG (Module) + Runtime (Module) + Runtime (Class) + Store (Module) + Store (Class) + Entry (Class) + StoreId (Class) + Util (Module, Ruby-only I guess) +``` + +I would name the types the same as in the Rust codebase, to avoid confusion. +Only exception would be the `Entry` class, which would be a `FileLockEntry` +underneath and if we adapt `libimagentrytag` and the other `libimagentry*` +libraries, we would extend this type. + -- cgit v1.2.3 From 238385a87f7df819cb351014225170ddda16cd42 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Fri, 20 Jan 2017 10:02:17 +0100 Subject: Allow unused variables here As the methods!() macro seems to introduce an unused variable "itself" for rustc 1.13 ... not sure whether this is valid or not. --- imag-ruby/src/store.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/imag-ruby/src/store.rs b/imag-ruby/src/store.rs index 04e24bfe..480c21da 100644 --- a/imag-ruby/src/store.rs +++ b/imag-ruby/src/store.rs @@ -17,6 +17,7 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // +#[allow(unused_variables)] pub mod storeid { use std::path::PathBuf; @@ -139,3 +140,4 @@ pub mod storeid { } } + -- cgit v1.2.3 From 78b1782f87498fd84a893be174b5f6e40752b88a Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Fri, 20 Jan 2017 10:04:12 +0100 Subject: Cargo.toml: Build as "dylib" --- imag-ruby/Cargo.toml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/imag-ruby/Cargo.toml b/imag-ruby/Cargo.toml index f307f28d..9144595c 100644 --- a/imag-ruby/Cargo.toml +++ b/imag-ruby/Cargo.toml @@ -13,6 +13,9 @@ documentation = "https://matthiasbeyer.github.io/imag/imag_documentation/index.h repository = "https://github.com/matthiasbeyer/imag" homepage = "http://imag-pim.org" +[lib] +crate-type = ["dylib"] + [dependencies] ruru = "0.9" lazy_static = "0.2" -- cgit v1.2.3 From 1c3205aa66b2a0ae5a3d7902f434cf68a9a207b1 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Fri, 20 Jan 2017 10:06:14 +0100 Subject: Add function to initialize the ruby extension --- imag-ruby/src/lib.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/imag-ruby/src/lib.rs b/imag-ruby/src/lib.rs index fd2f8d69..0f54e98e 100644 --- a/imag-ruby/src/lib.rs +++ b/imag-ruby/src/lib.rs @@ -27,3 +27,9 @@ extern crate libimagrt; #[macro_use] extern crate libimagutil; pub mod store; + +#[no_mangle] +pub extern fn imag_ruby_initialize() { + self::store::storeid::setup(); +} + -- cgit v1.2.3 From 0a25608ff0777aa147ad115999122f46ca0ec3f7 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Fri, 20 Jan 2017 10:37:58 +0100 Subject: Add Makefile for tests --- Makefile | 5 ++++- imag-ruby/Makefile | 20 ++++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 imag-ruby/Makefile diff --git a/Makefile b/Makefile index 719c0219..0dfea68c 100644 --- a/Makefile +++ b/Makefile @@ -65,7 +65,10 @@ bin-test: $(BIN_TARGET_TESTS) lib: $(LIB_TARGETS) @$(ECHO) "\t[ALLLIB ]" -lib-test: $(LIB_TARGETS_TEST) +lib-test: $(LIB_TARGETS_TEST) lib-imag-ruby-test + +lib-imag-ruby-test: + @$(MAKE) -C imag-ruby test: bin-test lib-test diff --git a/imag-ruby/Makefile b/imag-ruby/Makefile new file mode 100644 index 00000000..805b9a27 --- /dev/null +++ b/imag-ruby/Makefile @@ -0,0 +1,20 @@ +ECHO=$(shell which echo) -e +RUBY=$(shell which ruby) +RUBY_TESTS=$(shell find ./test -maxdepth 1 -name "*.rb" -type f) +RUBY_TEST_TARGETS=$(foreach x,$(subst ,,$(RUBY_TESTS)),$(x)) + +all: lib + +lib: + $(MAKE) -C .. imag-ruby + +lib-release: + $(MAKE) -C .. imag-ruby-release + +test: lib $(RUBY_TEST_TARGETS) + +$(RUBY_TEST_TARGETS): %: lib .FORCE + @$(ECHO) "\t[TEST ]:\t$@" + @$(RUBY) $(subst -test,,$@) + +.FORCE: -- cgit v1.2.3 From 31b64c4de7d22fd465a28180ad03ab7d1054883b Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Fri, 20 Jan 2017 10:38:06 +0100 Subject: Add mini test example --- imag-ruby/test/test_store_id_load.rb | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 imag-ruby/test/test_store_id_load.rb diff --git a/imag-ruby/test/test_store_id_load.rb b/imag-ruby/test/test_store_id_load.rb new file mode 100644 index 00000000..9d46ab01 --- /dev/null +++ b/imag-ruby/test/test_store_id_load.rb @@ -0,0 +1,11 @@ +#!/usr/bin/env ruby + +require 'fiddle' + +lib = Fiddle::dlopen './target/debug/libimag_ruby.so' +Fiddle::Function::new(lib['imag_ruby_initialize'], [], Fiddle::TYPE_VOIDP).call + +works = (not RStoreId.new_baseless("test").nil?) + +puts "Works: #{works}" + -- cgit v1.2.3 From 4f1cf691fd7dd00a7bc587bf1230506a3e61b65d Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Fri, 20 Jan 2017 10:41:33 +0100 Subject: Move: imag-ruby -> libimagruby --- Makefile | 2 +- imag-ruby/Cargo.toml | 35 -------- imag-ruby/Makefile | 20 ----- imag-ruby/README.md | 36 --------- imag-ruby/src/lib.rs | 35 -------- imag-ruby/src/store.rs | 143 --------------------------------- imag-ruby/test/test_store_id_load.rb | 11 --- libimagruby/Cargo.toml | 35 ++++++++ libimagruby/Makefile | 20 +++++ libimagruby/README.md | 36 +++++++++ libimagruby/src/lib.rs | 35 ++++++++ libimagruby/src/store.rs | 143 +++++++++++++++++++++++++++++++++ libimagruby/test/test_store_id_load.rb | 11 +++ 13 files changed, 281 insertions(+), 281 deletions(-) delete mode 100644 imag-ruby/Cargo.toml delete mode 100644 imag-ruby/Makefile delete mode 100644 imag-ruby/README.md delete mode 100644 imag-ruby/src/lib.rs delete mode 100644 imag-ruby/src/store.rs delete mode 100644 imag-ruby/test/test_store_id_load.rb create mode 100644 libimagruby/Cargo.toml create mode 100644 libimagruby/Makefile create mode 100644 libimagruby/README.md create mode 100644 libimagruby/src/lib.rs create mode 100644 libimagruby/src/store.rs create mode 100644 libimagruby/test/test_store_id_load.rb diff --git a/Makefile b/Makefile index 0dfea68c..c6d12065 100644 --- a/Makefile +++ b/Makefile @@ -68,7 +68,7 @@ lib: $(LIB_TARGETS) lib-test: $(LIB_TARGETS_TEST) lib-imag-ruby-test lib-imag-ruby-test: - @$(MAKE) -C imag-ruby + @$(MAKE) -C libimagruby test: bin-test lib-test diff --git a/imag-ruby/Cargo.toml b/imag-ruby/Cargo.toml deleted file mode 100644 index 9144595c..00000000 --- a/imag-ruby/Cargo.toml +++ /dev/null @@ -1,35 +0,0 @@ -[package] -name = "imag-ruby" -version = "0.1.0" -authors = ["Matthias Beyer "] - -description = "Library for the imag core distribution" - -keywords = ["imag", "PIM", "personal", "information", "management"] -readme = "../README.md" -license = "LGPL-2.1" - -documentation = "https://matthiasbeyer.github.io/imag/imag_documentation/index.html" -repository = "https://github.com/matthiasbeyer/imag" -homepage = "http://imag-pim.org" - -[lib] -crate-type = ["dylib"] - -[dependencies] -ruru = "0.9" -lazy_static = "0.2" -log = "0.3" - -[dependencies.libimagerror] -path = "../libimagerror" - -[dependencies.libimagrt] -path = "../libimagrt" - -[dependencies.libimagstore] -path = "../libimagstore" - -[dependencies.libimagutil] -path = "../libimagutil" - diff --git a/imag-ruby/Makefile b/imag-ruby/Makefile deleted file mode 100644 index 805b9a27..00000000 --- a/imag-ruby/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -ECHO=$(shell which echo) -e -RUBY=$(shell which ruby) -RUBY_TESTS=$(shell find ./test -maxdepth 1 -name "*.rb" -type f) -RUBY_TEST_TARGETS=$(foreach x,$(subst ,,$(RUBY_TESTS)),$(x)) - -all: lib - -lib: - $(MAKE) -C .. imag-ruby - -lib-release: - $(MAKE) -C .. imag-ruby-release - -test: lib $(RUBY_TEST_TARGETS) - -$(RUBY_TEST_TARGETS): %: lib .FORCE - @$(ECHO) "\t[TEST ]:\t$@" - @$(RUBY) $(subst -test,,$@) - -.FORCE: diff --git a/imag-ruby/README.md b/imag-ruby/README.md deleted file mode 100644 index 92939c35..00000000 --- a/imag-ruby/README.md +++ /dev/null @@ -1,36 +0,0 @@ -# imag-ruby - -A Ruby gem for scripting imag modules. - -This crate contains both the Rust bindings for imag using `ruru` and a bunch of -wrapper code for the actual `imag` gem. - -## Why another layer of indirection? - -As "ruru" does not yet support modules, which is sad btw, we would end up with -functions for all the things. - -E.G.: `imag_runtime_setup()` instead of `IMAG::Runtime::setup()` - -I want to add a Ruby gem to wrap these things. -So basically a piece of ruby which uses `imag.rb` (the Rust gem) to build -`imag` as a gem which then exports a fine module system. - -## Ideas for module system: - -```text -IMAG (Module) - Runtime (Module) - Runtime (Class) - Store (Module) - Store (Class) - Entry (Class) - StoreId (Class) - Util (Module, Ruby-only I guess) -``` - -I would name the types the same as in the Rust codebase, to avoid confusion. -Only exception would be the `Entry` class, which would be a `FileLockEntry` -underneath and if we adapt `libimagentrytag` and the other `libimagentry*` -libraries, we would extend this type. - diff --git a/imag-ruby/src/lib.rs b/imag-ruby/src/lib.rs deleted file mode 100644 index 0f54e98e..00000000 --- a/imag-ruby/src/lib.rs +++ /dev/null @@ -1,35 +0,0 @@ -// -// imag - the personal information management suite for the commandline -// Copyright (C) 2015, 2016 Matthias Beyer and contributors -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; version -// 2.1 of the License. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -// - -#[macro_use] extern crate ruru; -#[macro_use] extern crate lazy_static; -#[macro_use] extern crate log; - -#[macro_use] extern crate libimagerror; -extern crate libimagstore; -extern crate libimagrt; -#[macro_use] extern crate libimagutil; - -pub mod store; - -#[no_mangle] -pub extern fn imag_ruby_initialize() { - self::store::storeid::setup(); -} - diff --git a/imag-ruby/src/store.rs b/imag-ruby/src/store.rs deleted file mode 100644 index 480c21da..00000000 --- a/imag-ruby/src/store.rs +++ /dev/null @@ -1,143 +0,0 @@ -// -// imag - the personal information management suite for the commandline -// Copyright (C) 2015, 2016 Matthias Beyer and contributors -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; version -// 2.1 of the License. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -// - -#[allow(unused_variables)] -pub mod storeid { - use std::path::PathBuf; - - use ruru::{Class, Object, AnyObject, Boolean, RString, NilClass}; - - use libimagstore::storeid::StoreId; - - wrappable_struct!(StoreId, StoreIdWrapper, STOREID_WRAPPER); - class!(RStoreId); - - methods!( - RStoreId, - itself, - - fn r_storeid_new(base: RString, id: RString) -> AnyObject { - let base = match base.map(|b| b.to_string()).map(PathBuf::from) { - Ok(base) => base, - Err(e) => { - error!("Building StoreId object failed: {:?}", e); - return AnyObject::from(NilClass::new().value()); - }, - }; - - let id = match id.map(|id| id.to_string()).map(PathBuf::from) { - Ok(id) => id, - Err(e) => { - error!("Building StoreId object failed: {:?}", e); - return AnyObject::from(NilClass::new().value()); - }, - }; - - match StoreId::new(Some(base), id) { - Ok(sid) => Class::from_existing("RStoreId").wrap_data(sid, &*STOREID_WRAPPER), - Err(e) => { - error!("Building StoreId object failed: {:?}", e); - return AnyObject::from(NilClass::new().value()); - }, - } - } - - fn r_storeid_new_baseless(id: RString) -> AnyObject { - let id = match id.map(|id| id.to_string()).map(PathBuf::from) { - Ok(id) => id, - Err(e) => { - error!("Building StoreId object failed: {:?}", e); - return AnyObject::from(NilClass::new().value()); - }, - }; - - match StoreId::new(None, id) { - Ok(sid) => Class::from_existing("RStoreId").wrap_data(sid, &*STOREID_WRAPPER), - Err(e) => { - error!("Building StoreId object failed: {:?}", e); - return AnyObject::from(NilClass::new().value()); - }, - } - } - - fn r_storeid_without_base() -> RStoreId { - let withoutbase : StoreId = itself.get_data(&*STOREID_WRAPPER).clone().without_base(); - Class::from_existing("RStoreId").wrap_data(withoutbase, &*STOREID_WRAPPER) - } - - fn r_storeid_with_base(base: RString) -> AnyObject { - let base : PathBuf = match base.map(|b| b.to_string()).map(PathBuf::from) { - Ok(pb) => pb, - Err(e) => { - error!("Error: {:?}", e); - return AnyObject::from(NilClass::new().value()); - }, - }; - let withoutbase : StoreId = itself.get_data(&*STOREID_WRAPPER).clone().with_base(base); - Class::from_existing("RStoreId").wrap_data(withoutbase, &*STOREID_WRAPPER) - } - - fn r_storeid_into_pathbuf() -> AnyObject { - itself.get_data(&*STOREID_WRAPPER) - .clone() - .into_pathbuf() - .map(|pb| pb.to_str().map(String::from).unwrap()) - .as_ref() - .map(|s| AnyObject::from(RString::new(s).value())) - .unwrap_or(AnyObject::from(NilClass::new().value())) - } - - fn r_storeid_exists() -> Boolean { - Boolean::new(itself.get_data(&*STOREID_WRAPPER).exists()) - } - - fn r_storeid_to_str() -> AnyObject { - itself.get_data(&*STOREID_WRAPPER) - .to_str() - .as_ref() - .map(|s| AnyObject::from(RString::new(s).value())) - .unwrap_or(AnyObject::from(NilClass::new().value())) - } - - fn r_storeid_local() -> RString { - let local = itself.get_data(&*STOREID_WRAPPER).local(); - let local = local.to_str().unwrap(); - RString::new(local) - } - - ); - - pub fn setup() -> Class { - let mut class = Class::new("RStoreId", None); - class.define(|itself| { - itself.def_self("new" , r_storeid_new); - itself.def_self("new_baseless" , r_storeid_new_baseless); - - itself.def("without_base" , r_storeid_without_base); - itself.def("with_base" , r_storeid_with_base); - itself.def("into_pathbuf" , r_storeid_into_pathbuf); - itself.def("exists" , r_storeid_exists); - itself.def("to_str" , r_storeid_to_str); - itself.def("local" , r_storeid_local); - }); - class - } - -} - diff --git a/imag-ruby/test/test_store_id_load.rb b/imag-ruby/test/test_store_id_load.rb deleted file mode 100644 index 9d46ab01..00000000 --- a/imag-ruby/test/test_store_id_load.rb +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/env ruby - -require 'fiddle' - -lib = Fiddle::dlopen './target/debug/libimag_ruby.so' -Fiddle::Function::new(lib['imag_ruby_initialize'], [], Fiddle::TYPE_VOIDP).call - -works = (not RStoreId.new_baseless("test").nil?) - -puts "Works: #{works}" - diff --git a/libimagruby/Cargo.toml b/libimagruby/Cargo.toml new file mode 100644 index 00000000..a83842d2 --- /dev/null +++ b/libimagruby/Cargo.toml @@ -0,0 +1,35 @@ +[package] +name = "libimagruby" +version = "0.1.0" +authors = ["Matthias Beyer "] + +description = "Library for the imag core distribution" + +keywords = ["imag", "PIM", "personal", "information", "management"] +readme = "../README.md" +license = "LGPL-2.1" + +documentation = "https://matthiasbeyer.github.io/imag/imag_documentation/index.html" +repository = "https://github.com/matthiasbeyer/imag" +homepage = "http://imag-pim.org" + +[lib] +crate-type = ["dylib"] + +[dependencies] +ruru = "0.9" +lazy_static = "0.2" +log = "0.3" + +[dependencies.libimagerror] +path = "../libimagerror" + +[dependencies.libimagrt] +path = "../libimagrt" + +[dependencies.libimagstore] +path = "../libimagstore" + +[dependencies.libimagutil] +path = "../libimagutil" + diff --git a/libimagruby/Makefile b/libimagruby/Makefile new file mode 100644 index 00000000..f7ed82d6 --- /dev/null +++ b/libimagruby/Makefile @@ -0,0 +1,20 @@ +ECHO=$(shell which echo) -e +RUBY=$(shell which ruby) +RUBY_TESTS=$(shell find ./test -maxdepth 1 -name "*.rb" -type f) +RUBY_TEST_TARGETS=$(foreach x,$(subst ,,$(RUBY_TESTS)),$(x)) + +all: lib + +lib: + $(MAKE) -C .. libimagruby + +lib-release: + $(MAKE) -C .. libimagruby-release + +test: lib $(RUBY_TEST_TARGETS) + +$(RUBY_TEST_TARGETS): %: lib .FORCE + @$(ECHO) "\t[TEST ]:\t$@" + @$(RUBY) $(subst -test,,$@) + +.FORCE: diff --git a/libimagruby/README.md b/libimagruby/README.md new file mode 100644 index 00000000..92939c35 --- /dev/null +++ b/libimagruby/README.md @@ -0,0 +1,36 @@ +# imag-ruby + +A Ruby gem for scripting imag modules. + +This crate contains both the Rust bindings for imag using `ruru` and a bunch of +wrapper code for the actual `imag` gem. + +## Why another layer of indirection? + +As "ruru" does not yet support modules, which is sad btw, we would end up with +functions for all the things. + +E.G.: `imag_runtime_setup()` instead of `IMAG::Runtime::setup()` + +I want to add a Ruby gem to wrap these things. +So basically a piece of ruby which uses `imag.rb` (the Rust gem) to build +`imag` as a gem which then exports a fine module system. + +## Ideas for module system: + +```text +IMAG (Module) + Runtime (Module) + Runtime (Class) + Store (Module) + Store (Class) + Entry (Class) + StoreId (Class) + Util (Module, Ruby-only I guess) +``` + +I would name the types the same as in the Rust codebase, to avoid confusion. +Only exception would be the `Entry` class, which would be a `FileLockEntry` +underneath and if we adapt `libimagentrytag` and the other `libimagentry*` +libraries, we would extend this type. + diff --git a/libimagruby/src/lib.rs b/libimagruby/src/lib.rs new file mode 100644 index 00000000..0f54e98e --- /dev/null +++ b/libimagruby/src/lib.rs @@ -0,0 +1,35 @@ +// +// imag - the personal information management suite for the commandline +// Copyright (C) 2015, 2016 Matthias Beyer and contributors +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; version +// 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// + +#[macro_use] extern crate ruru; +#[macro_use] extern crate lazy_static; +#[macro_use] extern crate log; + +#[macro_use] extern crate libimagerror; +extern crate libimagstore; +extern crate libimagrt; +#[macro_use] extern crate libimagutil; + +pub mod store; + +#[no_mangle] +pub extern fn imag_ruby_initialize() { + self::store::storeid::setup(); +} + diff --git a/libimagruby/src/store.rs b/libimagruby/src/store.rs new file mode 100644 index 00000000..480c21da --- /dev/null +++ b/libimagruby/src/store.rs @@ -0,0 +1,143 @@ +// +// imag - the personal information management suite for the commandline +// Copyright (C) 2015, 2016 Matthias Beyer and contributors +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; version +// 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// + +#[allow(unused_variables)] +pub mod storeid { + use std::path::PathBuf; + + use ruru::{Class, Object, AnyObject, Boolean, RString, NilClass}; + + use libimagstore::storeid::StoreId; + + wrappable_struct!(StoreId, StoreIdWrapper, STOREID_WRAPPER); + class!(RStoreId); + + methods!( + RStoreId, + itself, + + fn r_storeid_new(base: RString, id: RString) -> AnyObject { + let base = match base.map(|b| b.to_string()).map(PathBuf::from) { + Ok(base) => base, + Err(e) => { + error!("Building StoreId object failed: {:?}", e); + return AnyObject::from(NilClass::new().value()); + }, + }; + + let id = match id.map(|id| id.to_string()).map(PathBuf::from) { + Ok(id) => id, + Err(e) => { + error!("Building StoreId object failed: {:?}", e); + return AnyObject::from(NilClass::new().value()); + }, + }; + + match StoreId::new(Some(base), id) { + Ok(sid) => Class::from_existing("RStoreId").wrap_data(sid, &*STOREID_WRAPPER), + Err(e) => { + error!("Building StoreId object failed: {:?}", e); + return AnyObject::from(NilClass::new().value()); + }, + } + } + + fn r_storeid_new_baseless(id: RString) -> AnyObject { + let id = match id.map(|id| id.to_string()).map(PathBuf::from) { + Ok(id) => id, + Err(e) => { + error!("Building StoreId object failed: {:?}", e); + return AnyObject::from(NilClass::new().value()); + }, + }; + + match StoreId::new(None, id) { + Ok(sid) => Class::from_existing("RStoreId").wrap_data(sid, &*STOREID_WRAPPER), + Err(e) => { + error!("Building StoreId object failed: {:?}", e); + return AnyObject::from(NilClass::new().value()); + }, + } + } + + fn r_storeid_without_base() -> RStoreId { + let withoutbase : StoreId = itself.get_data(&*STOREID_WRAPPER).clone().without_base(); + Class::from_existing("RStoreId").wrap_data(withoutbase, &*STOREID_WRAPPER) + } + + fn r_storeid_with_base(base: RString) -> AnyObject { + let base : PathBuf = match base.map(|b| b.to_string()).map(PathBuf::from) { + Ok(pb) => pb, + Err(e) => { + error!("Error: {:?}", e); + return AnyObject::from(NilClass::new().value()); + }, + }; + let withoutbase : StoreId = itself.get_data(&*STOREID_WRAPPER).clone().with_base(base); + Class::from_existing("RStoreId").wrap_data(withoutbase, &*STOREID_WRAPPER) + } + + fn r_storeid_into_pathbuf() -> AnyObject { + itself.get_data(&*STOREID_WRAPPER) + .clone() + .into_pathbuf() + .map(|pb| pb.to_str().map(String::from).unwrap()) + .as_ref() + .map(|s| AnyObject::from(RString::new(s).value())) + .unwrap_or(AnyObject::from(NilClass::new().value())) + } + + fn r_storeid_exists() -> Boolean { + Boolean::new(itself.get_data(&*STOREID_WRAPPER).exists()) + } + + fn r_storeid_to_str() -> AnyObject { + itself.get_data(&*STOREID_WRAPPER) + .to_str() + .as_ref() + .map(|s| AnyObject::from(RString::new(s).value())) + .unwrap_or(AnyObject::from(NilClass::new().value())) + } + + fn r_storeid_local() -> RString { + let local = itself.get_data(&*STOREID_WRAPPER).local(); + let local = local.to_str().unwrap(); + RString::new(local) + } + + ); + + pub fn setup() -> Class { + let mut class = Class::new("RStoreId", None); + class.define(|itself| { + itself.def_self("new" , r_storeid_new); + itself.def_self("new_baseless" , r_storeid_new_baseless); + + itself.def("without_base" , r_storeid_without_base); + itself.def("with_base" , r_storeid_with_base); + itself.def("into_pathbuf" , r_storeid_into_pathbuf); + itself.def("exists" , r_storeid_exists); + itself.def("to_str" , r_storeid_to_str); + itself.def("local" , r_storeid_local); + }); + class + } + +} + diff --git a/libimagruby/test/test_store_id_load.rb b/libimagruby/test/test_store_id_load.rb new file mode 100644 index 00000000..9d46ab01 --- /dev/null +++ b/libimagruby/test/test_store_id_load.rb @@ -0,0 +1,11 @@ +#!/usr/bin/env ruby + +require 'fiddle' + +lib = Fiddle::dlopen './target/debug/libimag_ruby.so' +Fiddle::Function::new(lib['imag_ruby_initialize'], [], Fiddle::TYPE_VOIDP).call + +works = (not RStoreId.new_baseless("test").nil?) + +puts "Works: #{works}" + -- cgit v1.2.3 From 8419be1195d294a5642540da4568802b94ca2391 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Fri, 20 Jan 2017 10:45:25 +0100 Subject: Disable ruby testing in lib-test as travis-ci does not have ruby 2.3.0 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index c6d12065..bd42d030 100644 --- a/Makefile +++ b/Makefile @@ -65,7 +65,7 @@ bin-test: $(BIN_TARGET_TESTS) lib: $(LIB_TARGETS) @$(ECHO) "\t[ALLLIB ]" -lib-test: $(LIB_TARGETS_TEST) lib-imag-ruby-test +lib-test: $(LIB_TARGETS_TEST) lib-imag-ruby-test: @$(MAKE) -C libimagruby -- cgit v1.2.3 From 9a47313adc11fb9955f00a279e7be101dfe1a939 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Fri, 20 Jan 2017 10:49:38 +0100 Subject: Add TODOs in code --- libimagruby/src/store.rs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/libimagruby/src/store.rs b/libimagruby/src/store.rs index 480c21da..82b32984 100644 --- a/libimagruby/src/store.rs +++ b/libimagruby/src/store.rs @@ -36,6 +36,7 @@ pub mod storeid { let base = match base.map(|b| b.to_string()).map(PathBuf::from) { Ok(base) => base, Err(e) => { + // TODO: Exception! error!("Building StoreId object failed: {:?}", e); return AnyObject::from(NilClass::new().value()); }, @@ -44,6 +45,7 @@ pub mod storeid { let id = match id.map(|id| id.to_string()).map(PathBuf::from) { Ok(id) => id, Err(e) => { + // TODO: Exception! error!("Building StoreId object failed: {:?}", e); return AnyObject::from(NilClass::new().value()); }, @@ -52,6 +54,7 @@ pub mod storeid { match StoreId::new(Some(base), id) { Ok(sid) => Class::from_existing("RStoreId").wrap_data(sid, &*STOREID_WRAPPER), Err(e) => { + // TODO: Exception! error!("Building StoreId object failed: {:?}", e); return AnyObject::from(NilClass::new().value()); }, @@ -62,6 +65,7 @@ pub mod storeid { let id = match id.map(|id| id.to_string()).map(PathBuf::from) { Ok(id) => id, Err(e) => { + // TODO: Exception! error!("Building StoreId object failed: {:?}", e); return AnyObject::from(NilClass::new().value()); }, @@ -70,6 +74,7 @@ pub mod storeid { match StoreId::new(None, id) { Ok(sid) => Class::from_existing("RStoreId").wrap_data(sid, &*STOREID_WRAPPER), Err(e) => { + // TODO: Exception! error!("Building StoreId object failed: {:?}", e); return AnyObject::from(NilClass::new().value()); }, @@ -85,6 +90,7 @@ pub mod storeid { let base : PathBuf = match base.map(|b| b.to_string()).map(PathBuf::from) { Ok(pb) => pb, Err(e) => { + // TODO: Exception! error!("Error: {:?}", e); return AnyObject::from(NilClass::new().value()); }, @@ -97,9 +103,11 @@ pub mod storeid { itself.get_data(&*STOREID_WRAPPER) .clone() .into_pathbuf() + // TODO: No unwraps .map(|pb| pb.to_str().map(String::from).unwrap()) .as_ref() .map(|s| AnyObject::from(RString::new(s).value())) + // TODO: Exception! .unwrap_or(AnyObject::from(NilClass::new().value())) } @@ -112,12 +120,13 @@ pub mod storeid { .to_str() .as_ref() .map(|s| AnyObject::from(RString::new(s).value())) + // TODO: Exception! .unwrap_or(AnyObject::from(NilClass::new().value())) } fn r_storeid_local() -> RString { let local = itself.get_data(&*STOREID_WRAPPER).local(); - let local = local.to_str().unwrap(); + let local = local.to_str().unwrap(); // TODO: No unwraps RString::new(local) } @@ -140,4 +149,3 @@ pub mod storeid { } } - -- cgit v1.2.3 From f7df36c9494c4531ef10aaf5c8598cbf392002b3 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Fri, 20 Jan 2017 10:49:45 +0100 Subject: Formatting --- libimagruby/src/store.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/libimagruby/src/store.rs b/libimagruby/src/store.rs index 82b32984..1cc03332 100644 --- a/libimagruby/src/store.rs +++ b/libimagruby/src/store.rs @@ -135,16 +135,16 @@ pub mod storeid { pub fn setup() -> Class { let mut class = Class::new("RStoreId", None); class.define(|itself| { - itself.def_self("new" , r_storeid_new); - itself.def_self("new_baseless" , r_storeid_new_baseless); - - itself.def("without_base" , r_storeid_without_base); - itself.def("with_base" , r_storeid_with_base); - itself.def("into_pathbuf" , r_storeid_into_pathbuf); - itself.def("exists" , r_storeid_exists); - itself.def("to_str" , r_storeid_to_str); - itself.def("local" , r_storeid_local); - }); + itself.def_self("new" , r_storeid_new); + itself.def_self("new_baseless" , r_storeid_new_baseless); + + itself.def("without_base" , r_storeid_without_base); + itself.def("with_base" , r_storeid_with_base); + itself.def("into_pathbuf" , r_storeid_into_pathbuf); + itself.def("exists" , r_storeid_exists); + itself.def("to_str" , r_storeid_to_str); + itself.def("local" , r_storeid_local); + }); class } -- cgit v1.2.3 From d617c5bcc94db012d06996f63e5796660b8a7b82 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Fri, 20 Jan 2017 13:09:51 +0100 Subject: Add dep: toml --- libimagruby/Cargo.toml | 1 + libimagruby/src/lib.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/libimagruby/Cargo.toml b/libimagruby/Cargo.toml index a83842d2..3c3ff30f 100644 --- a/libimagruby/Cargo.toml +++ b/libimagruby/Cargo.toml @@ -20,6 +20,7 @@ crate-type = ["dylib"] ruru = "0.9" lazy_static = "0.2" log = "0.3" +toml = "0.2" [dependencies.libimagerror] path = "../libimagerror" diff --git a/libimagruby/src/lib.rs b/libimagruby/src/lib.rs index 0f54e98e..f7702087 100644 --- a/libimagruby/src/lib.rs +++ b/libimagruby/src/lib.rs @@ -20,6 +20,7 @@ #[macro_use] extern crate ruru; #[macro_use] extern crate lazy_static; #[macro_use] extern crate log; +extern crate toml; #[macro_use] extern crate libimagerror; extern crate libimagstore; -- cgit v1.2.3 From a23534bf6aacfc8cdb8530d05b2367e76a0d190b Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Fri, 20 Jan 2017 11:12:06 +0100 Subject: Add store::entry::RFileLockEntry --- libimagruby/src/store.rs | 193 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 193 insertions(+) diff --git a/libimagruby/src/store.rs b/libimagruby/src/store.rs index 1cc03332..a1e14feb 100644 --- a/libimagruby/src/store.rs +++ b/libimagruby/src/store.rs @@ -149,3 +149,196 @@ pub mod storeid { } } + +#[allow(unused_variables)] +pub mod store { + pub mod entry { + use std::collections::BTreeMap; + use std::error::Error; + use std::ops::Deref; + use std::ops::DerefMut; + + use ruru::{Class, Object, Array, Hash, Fixnum, Float, Symbol, AnyObject, Boolean, RString, VM}; + + use libimagstore::store::FileLockEntry as FLE; + use libimagstore::store::EntryHeader; + use libimagstore::store::EntryContent; + use libimagstore::store::Entry; + + pub struct FLECustomWrapper(Box>); + + impl Deref for FLECustomWrapper { + type Target = Box>; + + fn deref(&self) -> &Self::Target { + &self.0 + } + } + + impl DerefMut for FLECustomWrapper { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } + } + + wrappable_struct!(FLECustomWrapper, FileLockEntryWrapper, FLE_WRAPPER); + class!(RFileLockEntry); + + wrappable_struct!(EntryHeader, EntryHeaderWrapper, ENTRY_HEADER_WRAPPER); + class!(REntryHeader); + methods!( + REntryHeader, + itself, + + fn r_entry_header_new() -> AnyObject { + Class::from_existing("REntryHeader") + .wrap_data(EntryHeader::new(), &*ENTRY_HEADER_WRAPPER) + } + + fn r_entry_header_insert(spec: RString, obj: AnyObject) -> Boolean { + use toml::Value; + use ruru::types::ValueType; + + fn do_insert(eh: &mut EntryHeader, spec: &str, v: Value) -> Boolean { + match eh.insert(spec, v) { + Ok(b) => Boolean::new(b), + Err(e) => { + VM::raise(Class::from_existing("RuntimeError"), e.description()); + return Boolean::new(false); + } + } + } + + fn to_value(obj: AnyObject) -> Result { + match obj.value().ty() { + ValueType::Fixnum => + Ok(Value::Integer(obj.try_convert_to::().unwrap().to_i64())), + + ValueType::Float => + Ok(Value::Float(obj.try_convert_to::().unwrap().to_f64())), + + ValueType::RString => + Ok(Value::String(obj.try_convert_to::().unwrap().to_string())), + + ValueType::Symbol => + Ok(Value::String(obj.try_convert_to::().unwrap().to_string())), + + _ => Err(()), + } + } + + if let Err(ref error) = spec { // raise exception if "spec" is not a String + VM::raise(error.to_exception(), error.description()); + return Boolean::new(false); + } + + let spec = spec.unwrap().to_string(); // safe because of check above. + let obj = obj.unwrap(); // possibly not safe... TODO + match obj.value().ty() { + ValueType::Fixnum => { + let i = obj.try_convert_to::().unwrap().to_i64(); + do_insert(itself.get_data(&*ENTRY_HEADER_WRAPPER), &spec, Value::Integer(i)) + } + + ValueType::Float => { + let f = obj.try_convert_to::().unwrap().to_f64(); + do_insert(itself.get_data(&*ENTRY_HEADER_WRAPPER), &spec, Value::Float(f)) + } + + ValueType::RString => { + let s = obj.try_convert_to::().unwrap().to_string(); + do_insert(itself.get_data(&*ENTRY_HEADER_WRAPPER), &spec, Value::String(s)) + } + + ValueType::Symbol => { + let s = obj.try_convert_to::().unwrap().to_string(); + do_insert(itself.get_data(&*ENTRY_HEADER_WRAPPER), &spec, Value::String(s)) + } + + ValueType::Array => { + let vals = obj.try_convert_to::() + .unwrap() + .into_iter() + .map(to_value) + .map(|el| { + let e_class = Class::from_existing("ArgumentError"); + let err = "Arrays can only hold 'Fixnum', 'Float', 'String' or 'Symbol' in this API"; + el.map_err(|_| VM::raise(e_class, err)) + }) + .filter_map(|e| e.ok()) + .collect::>(); + + do_insert(itself.get_data(&*ENTRY_HEADER_WRAPPER), &spec, Value::Array(vals)) + } + + ValueType::Hash => { + let mut btm = BTreeMap::new(); + obj.try_convert_to::() + .unwrap() + .each(|key, value| { + let key = match key.value().ty() { + ValueType::RString => obj.try_convert_to::().unwrap().to_string(), + ValueType::Symbol => obj.try_convert_to::().unwrap().to_string(), + _ => { + let e_class = Class::from_existing("ArgumentError"); + let err = "Hash must have 'String' or 'Symbol' as Key"; + VM::raise(e_class, err); + return; // from closure + } + }; + let value = match to_value(value) { + Err(e) => { + let e_class = Class::from_existing("ArgumentError"); + let err = "Hash must have 'Fixnum', 'Float', 'String' or 'Symbol' as value in this API"; + VM::raise(e_class, err); + return; // from closure + } + Ok(v) => v, + }; + + btm.insert(key, value); + }); + + do_insert(itself.get_data(&*ENTRY_HEADER_WRAPPER), &spec, Value::Table(btm)) + } + + ValueType::Nil => { + VM::raise(Class::from_existing("ArgumentError"), "Unexpected Argument 'nil'"); + return Boolean::new(false); + } + + _ => { + VM::raise(Class::from_existing("ArgumentError"), "Unexpected Argument Type"); + return Boolean::new(false); + } + } + + } + + ); + + wrappable_struct!(EntryContent, EntryContentWrapper, ENTRY_CONTENT_WRAPPER); + class!(REntryContent); + + wrappable_struct!(Entry, EntryWrapper, ENTRY_WRAPPER); + class!(REntry); + + pub fn setup_filelockentry() -> Class { + let mut class = Class::new("RFileLockEntry", None); + class + } + + pub fn setup_entryheader() -> Class { + let mut class = Class::new("REntryHeader", None); + class + } + + pub fn setup_entrycontent() -> Class { + let string = Class::from_existing("String"); + let mut class = Class::new("REntryContent", Some(&string)); + class + } + } + +} + -- cgit v1.2.3 From 9d06fd8ea70ab8c16d136a3665aee43e92ef575d Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Fri, 20 Jan 2017 14:22:59 +0100 Subject: Add files for ruby/toml utils --- libimagruby/src/lib.rs | 2 ++ libimagruby/src/ruby_utils.rs | 43 +++++++++++++++++++++++++++++++++++++++++++ libimagruby/src/toml_utils.rs | 43 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 88 insertions(+) create mode 100644 libimagruby/src/ruby_utils.rs create mode 100644 libimagruby/src/toml_utils.rs diff --git a/libimagruby/src/lib.rs b/libimagruby/src/lib.rs index f7702087..49ee78c4 100644 --- a/libimagruby/src/lib.rs +++ b/libimagruby/src/lib.rs @@ -28,6 +28,8 @@ extern crate libimagrt; #[macro_use] extern crate libimagutil; pub mod store; +pub mod toml_utils; +pub mod ruby_utils; #[no_mangle] pub extern fn imag_ruby_initialize() { diff --git a/libimagruby/src/ruby_utils.rs b/libimagruby/src/ruby_utils.rs new file mode 100644 index 00000000..d8fb83a4 --- /dev/null +++ b/libimagruby/src/ruby_utils.rs @@ -0,0 +1,43 @@ +// +// imag - the personal information management suite for the commandline +// Copyright (C) 2015, 2016 Matthias Beyer and contributors +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; version +// 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// + +// Ruby -> Toml translation primitives + +use ruru::AnyObject; +use toml::Value; + +pub trait AsToml : Sized { + fn as_toml(&self) -> Value; +} + +pub trait IntoToml : AsToml { + fn into_toml(self) -> Value { + self.as_toml() + } +} +impl IntoToml for T { } + +impl AsToml for AnyObject { + + fn as_toml(&self) -> Value { + unimplemented!() + } + +} + diff --git a/libimagruby/src/toml_utils.rs b/libimagruby/src/toml_utils.rs new file mode 100644 index 00000000..61dd1c30 --- /dev/null +++ b/libimagruby/src/toml_utils.rs @@ -0,0 +1,43 @@ +// +// imag - the personal information management suite for the commandline +// Copyright (C) 2015, 2016 Matthias Beyer and contributors +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; version +// 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// + +// Toml -> Ruby translation primitives + +use ruru::AnyObject; +use toml::Value; + +pub trait AsRuby : Sized { + fn as_ruby(&self) -> AnyObject; +} + +pub trait IntoRuby : AsRuby { + fn into_ruby(self) -> AnyObject { + self.as_ruby() + } +} +impl IntoRuby for T { } + +impl AsRuby for Value { + + fn as_ruby(&self) -> AnyObject { + unimplemented!() + } + +} + -- cgit v1.2.3 From 6d623ddff243ea3589b4ae7a8ab3fa3ba4682a62 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Fri, 20 Jan 2017 14:40:51 +0100 Subject: Add Value::as_ruby() impl --- libimagruby/src/toml_utils.rs | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/libimagruby/src/toml_utils.rs b/libimagruby/src/toml_utils.rs index 61dd1c30..85df9dde 100644 --- a/libimagruby/src/toml_utils.rs +++ b/libimagruby/src/toml_utils.rs @@ -19,7 +19,7 @@ // Toml -> Ruby translation primitives -use ruru::AnyObject; +use ruru::{Object, AnyObject, RString, Fixnum, Float, Boolean, Hash, Array}; use toml::Value; pub trait AsRuby : Sized { @@ -36,7 +36,29 @@ impl IntoRuby for T { } impl AsRuby for Value { fn as_ruby(&self) -> AnyObject { - unimplemented!() + match *self { + Value::String(ref s) => RString::new(&s).to_any_object(), + Value::Integer(i) => Fixnum::new(i).to_any_object(), + Value::Float(f) => Float::new(f).to_any_object(), + Value::Boolean(b) => Boolean::new(b).to_any_object(), + Value::Datetime(ref s) => RString::new(&s).to_any_object(), + Value::Array(ref a) => { + let mut arr = Array::new(); + for obj in a.into_iter().map(AsRuby::as_ruby) { + arr.push(obj); + } + arr.to_any_object() + }, + Value::Table(ref t) => { + let mut h = Hash::new(); + for (k, v) in t.into_iter() { + let key = RString::new(k).to_any_object(); + let v = v.as_ruby(); + h.store(key, v); + } + h.to_any_object() + }, + } } } -- cgit v1.2.3 From 24c77be046705b99d6e265b6aec3a62afdc53b4a Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Fri, 20 Jan 2017 14:58:18 +0100 Subject: Add impl of as_toml() --- libimagruby/src/ruby_utils.rs | 129 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 127 insertions(+), 2 deletions(-) diff --git a/libimagruby/src/ruby_utils.rs b/libimagruby/src/ruby_utils.rs index d8fb83a4..94b922f7 100644 --- a/libimagruby/src/ruby_utils.rs +++ b/libimagruby/src/ruby_utils.rs @@ -19,9 +19,13 @@ // Ruby -> Toml translation primitives -use ruru::AnyObject; +use std::collections::BTreeMap; + +use ruru::{Object, AnyObject, Class, RString, Fixnum, Float, Symbol, Hash, Array, VM}; +use ruru::types::ValueType; use toml::Value; + pub trait AsToml : Sized { fn as_toml(&self) -> Value; } @@ -36,7 +40,128 @@ impl IntoToml for T { } impl AsToml for AnyObject { fn as_toml(&self) -> Value { - unimplemented!() + match self.value().ty() { + ValueType::None => { + Value::Boolean(false) + }, + ValueType::Object => { + let rte = Class::from_existing("TypeError"); + VM::raise(rte, "Cannot translate type '' to fit into TOML"); + Value::Boolean(false) + }, + ValueType::Class => { + let rte = Class::from_existing("TypeError"); + VM::raise(rte, "Cannot translate type '' to fit into TOML"); + Value::Boolean(false) + }, + ValueType::Module => { + let rte = Class::from_existing("TypeError"); + VM::raise(rte, "Cannot translate type '' to fit into TOML"); + Value::Boolean(false) + }, + ValueType::Float => + Value::Float(self.try_convert_to::().unwrap().to_f64()), + ValueType::RString => + Value::String(self.try_convert_to::().unwrap().to_string()), + ValueType::Regexp => { + let rte = Class::from_existing("TypeError"); + VM::raise(rte, "Cannot translate type '' to fit into TOML"); + Value::Boolean(false) + }, + ValueType::Array => { + let vals = self + .try_convert_to::() + .unwrap() + .into_iter() + .map(|v| v.as_toml()) + .collect::>(); + + Value::Array(vals) + }, + ValueType::Hash => { + let mut btm = BTreeMap::new(); + self.try_convert_to::() + .unwrap() + .each(|key, value| { + let key = match key.as_toml() { + Value::String(s) => s, + _ => { + let rte = Class::from_existing("TypeError"); + VM::raise(rte, "Can only have String or Symbol as Key for TOML maps"); + String::new() + } + }; + let value = value.as_toml(); + btm.insert(key, value); + }); + Value::Table(btm) + }, + ValueType::Struct => { + let rte = Class::from_existing("TypeError"); + VM::raise(rte, "Cannot translate type '' to fit into TOML"); + Value::Boolean(false) + }, + ValueType::Bignum => { + let rte = Class::from_existing("TypeError"); + VM::raise(rte, "Cannot translate type '' to fit into TOML"); + Value::Boolean(false) + }, + ValueType::File => { + let rte = Class::from_existing("TypeError"); + VM::raise(rte, "Cannot translate type '' to fit into TOML"); + Value::Boolean(false) + }, + ValueType::Data => { + let rte = Class::from_existing("TypeError"); + VM::raise(rte, "Cannot translate type '' to fit into TOML"); + Value::Boolean(false) + }, + ValueType::Match => { + let rte = Class::from_existing("TypeError"); + VM::raise(rte, "Cannot translate type '' to fit into TOML"); + Value::Boolean(false) + }, + ValueType::Complex => { + let rte = Class::from_existing("TypeError"); + VM::raise(rte, "Cannot translate type '' to fit into TOML"); + Value::Boolean(false) + }, + ValueType::Rational => { + let rte = Class::from_existing("TypeError"); + VM::raise(rte, "Cannot translate type '' to fit into TOML"); + Value::Boolean(false) + }, + ValueType::Nil => Value::Boolean(false), + ValueType::True => Value::Boolean(true), + V