diff options
author | Matthias Beyer <mail@beyermatthias.de> | 2018-02-14 14:09:59 +0100 |
---|---|---|
committer | Matthias Beyer <mail@beyermatthias.de> | 2018-02-19 12:14:32 +0100 |
commit | a1a85f40d0e1bccb1874fc300c8f3f7558aff677 (patch) | |
tree | df4f7fa2fc4bdfc921aff3794d530ad7d01036f3 | |
parent | 2328c8b2b01c60395aafce04cdd60596656c2696 (diff) |
Add default generators
-rw-r--r-- | lib/entry/libimagentryref/Cargo.toml | 15 | ||||
-rw-r--r-- | lib/entry/libimagentryref/src/generators/base.rs | 48 | ||||
-rw-r--r-- | lib/entry/libimagentryref/src/generators/mod.rs | 259 | ||||
-rw-r--r-- | lib/entry/libimagentryref/src/lib.rs | 13 |
4 files changed, 335 insertions, 0 deletions
diff --git a/lib/entry/libimagentryref/Cargo.toml b/lib/entry/libimagentryref/Cargo.toml index 5e1f7f9a..46178af7 100644 --- a/lib/entry/libimagentryref/Cargo.toml +++ b/lib/entry/libimagentryref/Cargo.toml @@ -30,3 +30,18 @@ libimagstore = { version = "0.7.0", path = "../../../lib/core/libimagstore" libimagerror = { version = "0.7.0", path = "../../../lib/core/libimagerror" } libimagentrylist = { version = "0.7.0", path = "../../../lib/entry/libimagentrylist" } libimagentryutil = { version = "0.7.0", path = "../../../lib/entry/libimagentryutil" } + +[dependencies.rust-crypto] +version = "0.2" +optional = true + +[features] +default = [] +generators = [] +generators-sha1 = ["rust-crypto"] +generators-sha224 = ["rust-crypto"] +generators-sha256 = ["rust-crypto"] +generators-sha384 = ["rust-crypto"] +generators-sha512 = ["rust-crypto"] +generators-sha3 = ["rust-crypto"] + diff --git a/lib/entry/libimagentryref/src/generators/base.rs b/lib/entry/libimagentryref/src/generators/base.rs new file mode 100644 index 00000000..aea60b28 --- /dev/null +++ b/lib/entry/libimagentryref/src/generators/base.rs @@ -0,0 +1,48 @@ +// +// imag - the personal information management suite for the commandline +// Copyright (C) 2015-2018 Matthias Beyer <mail@beyermatthias.de> 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 +// + +use std::path::Path; + +use libimagstore::storeid::StoreId; + +use error::RefError; +use refstore::UniqueRefPathGenerator; + +/// A base UniqueRefPathGenerator which must be overridden by the actual UniqueRefPathGenerator +/// which is provided by this crate +#[allow(dead_code)] +pub struct Base; + +impl UniqueRefPathGenerator for Base { + type Error = RefError; + + fn collection() -> &'static str { + "ref" + } + + fn unique_hash<A: AsRef<Path>>(_path: A) -> Result<String, Self::Error> { + // This has to be overridden + panic!("Not overridden base functionality. This is a BUG!") + } + + fn postprocess_storeid(sid: StoreId) -> Result<StoreId, Self::Error> { + Ok(sid) // default implementation + } +} + diff --git a/lib/entry/libimagentryref/src/generators/mod.rs b/lib/entry/libimagentryref/src/generators/mod.rs new file mode 100644 index 00000000..730fd640 --- /dev/null +++ b/lib/entry/libimagentryref/src/generators/mod.rs @@ -0,0 +1,259 @@ +// +// imag - the personal information management suite for the commandline +// Copyright (C) 2015-2018 Matthias Beyer <mail@beyermatthias.de> 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 +// + +//! Default generators +//! +//! This module provides a number of default `UniqueRefPathGenerator`s +//! which can be used for generating references. +//! +//! These generators are _NOT_ domain specific. So there won't be a "UniqueMailRefPathGenerator" in +//! here, for example. +//! +//! All these generators use "ref" as collection name. +//! They can be overridden using the `make_unique_ref_path_generator!()` convenience macro. +//! +//! # Note +//! +//! You must enable the appropriate crate feature to use any of the provided generators. With the +//! `generators` feature, you only get the convenience macro `make_unique_ref_path_generator!()`. +//! + +/// A convenience macro for wrapping a generator in a new one, reusing the functionality from the +/// underlying generator +/// +/// The UniqueRefPathGenerator must be in scope. +/// +/// The macro creates a new struct `$name` over `$underlying` and changes the collection name to +/// `$collectionname`. +/// If passed, the new implementation is used (defaults to the implementation from the underlying +/// generator). +/// If passed, the new postprocessing is used (defaults to not changing the StoreId) +/// +#[macro_export] +macro_rules! make_unique_ref_path_generator { + ( + $name:ident + over $underlying:ty + => with error $errtype:ty + => with collection name $collectionname:expr + ) => { + struct $name; + impl_unique_ref_path_generator_trait!( + $name + over $underlying + => with error $errtype + => with collection name $collectionname + => |p| { $underlying::unique_hash(p) } => |s| { Ok(s) } + ); + }; + + ( + $name:ident + over $underlying:ty + => with error $errtype:ty + => with collection name $collectionname:expr + => $impl:expr + ) => { + struct $name; + impl_unique_ref_path_generator_trait!( + $name + over $underlying + => with error $errtype + => with collection name $collectionname + => $impl => |sid| { Ok(sid) } + ); + }; + + ( + pub $name:ident + over $underlying:ty + => with error $errtype:ty + => with collection name $collectionname:expr + => $impl:expr + ) => { + make_unique_ref_path_generator!( + pub $name + over $underlying + => with error $errtype + => with collection name $collectionname + => $impl => |sid| { Ok(sid) } + ); + }; + + ( + pub $name:ident + over $underlying:ty + => with error $errtype:ty + => with collection name $collectionname:expr + => $impl:expr + => $postproc:expr + ) => { + pub struct $name; + impl_unique_ref_path_generator_trait!( + $name, $underlying, $errtype, $collectionname => $impl => $postproc + ); + }; +} + +macro_rules! impl_unique_ref_path_generator_trait { + ($name:ident, $underlying:ty, $errtype:ty, $collectionname:expr => $impl:expr => $postproc:expr) => { + impl $crate::refstore::UniqueRefPathGenerator for $name { + type Error = $errtype; + + fn collection() -> &'static str { + $collectionname + } + + fn unique_hash<A: AsRef<Path>>(path: A) -> Result<String, Self::Error> { + $impl(path) + } + + fn postprocess_storeid(sid: ::libimagstore::storeid::StoreId) + -> Result<::libimagstore::storeid::StoreId, Self::Error> + { + $postproc(sid) + } + } + } +} + + +#[cfg(any( + feature = "generators-sha1", + feature = "generators-sha224", + feature = "generators-sha256", + feature = "generators-sha384", + feature = "generators-sha512", + feature = "generators-sha3", + ))] +mod base; + +/// Helper macro for generating implementations for the various Sha algorithms +macro_rules! make_sha_mod { + { + $modname:ident, + $hashname:ident, + $hashingimpl:expr + } => { + pub mod $modname { + use std::path::Path; + use std::fs::OpenOptions; + use std::io::Read; + + use error::RefError as RE; + + use crypto::digest::Digest; + make_unique_ref_path_generator! ( + pub $hashname + over generators::base::Base + => with error RE + => with collection name "ref" + => |path| { + OpenOptions::new() + .read(true) + .write(false) + .create(false) + .open(path) + .map_err(RE::from) + .and_then(|mut file| { + let mut buffer = String::new(); + let _ = file.read_to_string(&mut buffer)?; + $hashingimpl(buffer) + }) + } + ); + + impl $hashname { + + /// Function which can be used by a wrapping UniqueRefPathGenerator to hash only N bytes. + pub fn hash_n_bytes<A: AsRef<Path>>(path: A, n: usize) -> Result<String, RE> { + OpenOptions::new() + .read(true) + .write(false) + .create(false) + .open(path) + .map_err(RE::from) + .and_then(|mut file| { + let mut buffer = Vec::with_capacity(n); + let _ = file.read_exact(&mut buffer)?; + let buffer = String::from_utf8(buffer)?; + $hashingimpl(buffer) + }) + } + + } + + } + } +} + +#[cfg(feature = "generators-sha1")] +make_sha_mod! { + sha1, Sha1, |buffer: String| { + let mut hasher = ::crypto::sha1::Sha1::new(); + hasher.input_str(&buffer); + Ok(String::from(hasher.result_str())) + } +} + +#[cfg(feature = "generators-sha224")] +make_sha_mod! { + sha224, Sha224, |buffer: String| { + let mut hasher = ::crypto::sha2::Sha224::new(); + hasher.input_str(&buffer); + Ok(String::from(hasher.result_str())) + } +} + +#[cfg(feature = "generators-sha256")] +make_sha_mod! { + sha256, Sha256, |buffer: String| { + let mut hasher = ::crypto::sha2::Sha256::new(); + hasher.input_str(&buffer); + Ok(String::from(hasher.result_str())) + } +} + +#[cfg(feature = "generators-sha384")] +make_sha_mod! { + sha384, Sha384, |buffer: String| { + let mut hasher = ::crypto::sha2::Sha384::new(); + hasher.input_str(&buffer); + Ok(String::from(hasher.result_str())) + } +} + +#[cfg(feature = "generators-sha512")] +make_sha_mod! { + sha512, Sha512, |buffer: String| { + let mut hasher = ::crypto::sha2::Sha512::new(); + hasher.input_str(&buffer); + Ok(String::from(hasher.result_str())) + } +} + +#[cfg(feature = "generators-sha3")] +make_sha_mod! { + sha3, Sha3, |buffer: String| { + let mut hasher = ::crypto::sha3::Sha3::sha3_256(); + hasher.input_str(&buffer); + Ok(String::from(hasher.result_str())) + } +} + diff --git a/lib/entry/libimagentryref/src/lib.rs b/lib/entry/libimagentryref/src/lib.rs index 7311d13b..39f3c546 100644 --- a/lib/entry/libimagentryref/src/lib.rs +++ b/lib/entry/libimagentryref/src/lib.rs @@ -52,3 +52,16 @@ pub mod error; pub mod reference; pub mod refstore; +#[cfg(any( + feature = "generators-sha1", + feature = "generators-sha224", + feature = "generators-sha256", + feature = "generators-sha384", + feature = "generators-sha512", + feature = "generators-sha3", +))] +extern crate crypto; + +#[cfg(feature = "generators")] +pub mod generators; + |