From a246144c26ae67db570661e8a6adf3602364a51a Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Wed, 29 Nov 2017 19:48:46 +0100 Subject: [PATCH] Add Is helper trait --- lib/entry/libimagentryutil/src/isa.rs | 100 ++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) diff --git a/lib/entry/libimagentryutil/src/isa.rs b/lib/entry/libimagentryutil/src/isa.rs index 09864fbb..de29f916 100644 --- a/lib/entry/libimagentryutil/src/isa.rs +++ b/lib/entry/libimagentryutil/src/isa.rs @@ -17,4 +17,104 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // +use error::EntryUtilError as EUE; +use error::Result; + +use toml::Value; +use toml_query::read::TomlValueReadExt; + +/// Trait to check whether an entry is a certain kind of entry +/// +/// If an entry is marked with a `bool` flag in the header to contain a certain amount of data (for +/// example a "wiki" entry may provide some meta information in the `[wiki]` section of its header), +/// this trait provides a check whether the entry has set the flag to `true` or `false`. +/// +/// # Note +/// +/// This trait is solely for library implementations, as convenience functionality for implementing +/// some function like this: +/// +/// # Example +/// +/// ``` +/// # extern crate libimagstore; +/// # #[macro_use] +/// # extern crate libimagentryutil; +/// +/// # use libimagentryutil::error::Result as Result; +/// use libimagentryutil::isa::IsKindHeaderPathProvider; +/// use libimagentryutil::isa::Is; +/// +/// trait WikiArticle { +/// fn is_wiki_article(&self) -> Result; +/// // ... +/// } +/// +/// provide_kindflag_path!(IsWikiEntry, "wiki.is_entry"); +/// +/// impl WikiArticle for ::libimagstore::store::Entry { +/// fn is_wiki_article(&self) -> Result { +/// self.is::() +/// } +/// } +/// +/// # fn main() { } +/// ``` +/// +/// # See also +/// +/// * Documentation for `IsKindHeaderPathProvider` +/// * Helper macro `provide_kindflag_path!()` +/// +pub trait Is { + fn is(&self) -> Result; +} + +impl Is for ::libimagstore::store::Entry { + fn is(&self) -> Result { + let field = T::kindflag_header_location(); + + match self.get_header().read(field) { + Ok(Some(&Value::Boolean(b))) => Ok(b), + Ok(Some(_)) => Err(format!("Field {} has not a boolean type", field)).map_err(EUE::from), + Ok(None) => Err(format!("Field {} not available", field)).map_err(EUE::from), + Err(e) => Err(EUE::from(e)) + } + } +} + + +/// The IsKindHeaderPathProvider trait provides a function `typeflag_header_location()` which +/// returns a `toml-query` path. +/// +/// This path points to a `bool` entry in the header of an entry which marks the entry to be an +/// entry of a certain kind. +/// +/// For example, an "Wiki" entry might contain a `true` at `"wiki.is_entry"` in the header. +/// This trait provides `"wiki.is_entry"`. +pub trait IsKindHeaderPathProvider { + fn kindflag_header_location() -> &'static str; +} + +/// Create (pub/non-pub) type for providing a `kindflag_header_location()` implementation. +#[macro_export] +macro_rules! provide_kindflag_path { + (pub $entry_header_path_provider_type:ident, $path:expr) => { + pub struct $entry_header_path_provider_type; + provide_kindflag_path!(impl for $entry_header_path_provider_type, $path); + }; + + ($entry_header_path_provider_type:ident, $path:expr) => { + struct $entry_header_path_provider_type; + provide_kindflag_path!(impl for $entry_header_path_provider_type, $path); + }; + + (impl for $entry_header_path_provider_type:ident, $path:expr) => { + impl IsKindHeaderPathProvider for $entry_header_path_provider_type { + fn kindflag_header_location() -> &'static str { + $path + } + } + }; +}