From a23534bf6aacfc8cdb8530d05b2367e76a0d190b Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Fri, 20 Jan 2017 11:12:06 +0100 Subject: [PATCH] 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 + } + } + +} +