From 188aacad75d5e50ba136e9a9e5b0da527d52ed44 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sun, 6 Dec 2015 13:09:51 +0100 Subject: [PATCH] Move FileHeader{Spec,Data} to own submodules --- src/module/bm/header.rs | 4 +- src/module/helpers/header/tags.rs | 4 +- src/module/helpers/mod.rs | 2 +- src/storage/file/header/data.rs | 37 ++++++ src/storage/file/header/mod.rs | 126 ++++++++++++++++++++ src/storage/file/header/spec.rs | 41 +++++++ src/storage/file/mod.rs | 192 +----------------------------- src/storage/json/parser.rs | 3 +- src/storage/parser.rs | 2 +- 9 files changed, 215 insertions(+), 196 deletions(-) create mode 100644 src/storage/file/header/data.rs create mode 100644 src/storage/file/header/mod.rs create mode 100644 src/storage/file/header/spec.rs diff --git a/src/module/bm/header.rs b/src/module/bm/header.rs index c25199aa..3cb4f75a 100644 --- a/src/module/bm/header.rs +++ b/src/module/bm/header.rs @@ -1,6 +1,6 @@ use module::helpers::header as headerhelpers; -use storage::file::FileHeaderData as FHD; -use storage::file::FileHeaderSpec as FHS; +use storage::file::header::data::FileHeaderData as FHD; +use storage::file::header::spec::FileHeaderSpec as FHS; pub fn get_spec() -> FHS { FHS::Map { diff --git a/src/module/helpers/header/tags.rs b/src/module/helpers/header/tags.rs index 970a07a5..2ad2e61b 100644 --- a/src/module/helpers/header/tags.rs +++ b/src/module/helpers/header/tags.rs @@ -3,7 +3,7 @@ */ pub mod spec { - use storage::file::FileHeaderSpec as FHS; + use storage::file::header::spec::FileHeaderSpec as FHS; use module::helpers::spec::{named_text, named_text_array}; pub fn url_key() -> FHS { @@ -18,7 +18,7 @@ pub mod spec { pub mod data { use std::ops::Deref; - use storage::file::FileHeaderData as FHD; + use storage::file::header::data::FileHeaderData as FHD; pub fn build_tag_array(tags: &Vec) -> FHD { let texttags = tags.into_iter().map(|t| FHD::Text(t.clone())).collect(); diff --git a/src/module/helpers/mod.rs b/src/module/helpers/mod.rs index e06a668b..8b501b4a 100644 --- a/src/module/helpers/mod.rs +++ b/src/module/helpers/mod.rs @@ -2,7 +2,7 @@ pub mod header; pub mod utils; pub mod spec { - use storage::file::FileHeaderSpec as FHS; + use storage::file::header::spec::FileHeaderSpec as FHS; pub fn named_text(name: &str) -> FHS { FHS::Key { name: String::from(name), value_type: Box::new(FHS::Text) } diff --git a/src/storage/file/header/data.rs b/src/storage/file/header/data.rs new file mode 100644 index 00000000..f94a4b26 --- /dev/null +++ b/src/storage/file/header/data.rs @@ -0,0 +1,37 @@ +use regex::Regex; + +#[derive(Debug)] +#[derive(Clone)] +pub enum FileHeaderData { + Null, + Bool(bool), + Integer(i64), + UInteger(u64), + Float(f64), + Text(String), + Key { name: String, value: Box }, + Map { keys: Vec }, + Array { values: Box> }, +} + +impl FileHeaderData { + + pub fn matches_with(&self, r: &Regex) -> bool { + match self { + &FileHeaderData::Text(ref t) => r.is_match(&t[..]), + &FileHeaderData::Key{name: ref n, value: ref val} => { + r.is_match(n) || val.matches_with(r) + }, + + &FileHeaderData::Map{keys: ref dks} => { + dks.iter().any(|x| x.matches_with(r)) + }, + + &FileHeaderData::Array{values: ref vs} => { + vs.iter().any(|x| x.matches_with(r)) + } + + _ => false, + } + } +} diff --git a/src/storage/file/header/mod.rs b/src/storage/file/header/mod.rs new file mode 100644 index 00000000..8725d40d --- /dev/null +++ b/src/storage/file/header/mod.rs @@ -0,0 +1,126 @@ +use std::error::Error; +use std::fmt::{Debug, Display, Formatter}; +use std::fmt; + +pub mod spec; +pub mod data; + +use self::data::*; +use self::spec::*; + +pub struct MatchError<'a> { + summary: String, + expected: &'a FileHeaderSpec, + found: &'a FileHeaderData +} + +impl<'a> MatchError<'a> { + + pub fn new(s: String, + ex: &'a FileHeaderSpec, + found: &'a FileHeaderData) -> MatchError<'a> { + MatchError { + summary: s, + expected: ex, + found: found, + } + } + + pub fn format(&self) -> String { + format!("MatchError: {:?}\nExpected: {:?}\nFound: {:?}\n", + self.summary, self.expected, self.found) + } +} + +impl<'a> Error for MatchError<'a> { + + fn description(&self) -> &str { + &self.summary[..] + } + + fn cause(&self) -> Option<&Error> { + None + } + +} + +impl<'a> Debug for MatchError<'a> { + + fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { + write!(fmt, "{}", self.format()); + Ok(()) + } + +} + +impl<'a> Display for MatchError<'a> { + + fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { + write!(fmt, "{}", self.format()); + Ok(()) + } + +} + +pub fn match_header_spec<'a>(spec: &'a FileHeaderSpec, data: &'a FileHeaderData) + -> Option> +{ + debug!("Start matching:\n'{:?}'\non\n{:?}", spec, data); + match (spec, data) { + (&FileHeaderSpec::Null, &FileHeaderData::Null) => { } + (&FileHeaderSpec::Bool, &FileHeaderData::Bool(_)) => { } + (&FileHeaderSpec::Integer, &FileHeaderData::Integer(_)) => { } + (&FileHeaderSpec::UInteger, &FileHeaderData::UInteger(_)) => { } + (&FileHeaderSpec::Float, &FileHeaderData::Float(_)) => { } + (&FileHeaderSpec::Text, &FileHeaderData::Text(_)) => { } + + ( + &FileHeaderSpec::Key{name: ref kname, value_type: ref vtype}, + &FileHeaderData::Key{name: ref n, value: ref val} + ) => { + debug!("Matching Key: '{:?}' == '{:?}', Value: '{:?}' == '{:?}'", + kname, n, + vtype, val); + if kname != n { + debug!("Keys not matching"); + unimplemented!(); + } + return match_header_spec(&*vtype, &*val); + } + + ( + &FileHeaderSpec::Map{keys: ref sks}, + &FileHeaderData::Map{keys: ref dks} + ) => { + debug!("Matching Map: '{:?}' == '{:?}'", sks, dks); + + for (s, d) in sks.iter().zip(dks.iter()) { + let res = match_header_spec(s, d); + if res.is_some() { + return res; + } + } + } + + ( + &FileHeaderSpec::Array{allowed_types: ref vtypes}, + &FileHeaderData::Array{values: ref vs} + ) => { + debug!("Matching Array: '{:?}' == '{:?}'", vtypes, vs); + for (t, v) in vtypes.iter().zip(vs.iter()) { + let res = match_header_spec(t, v); + if res.is_some() { + return res; + } + } + } + + (k, v) => { + return Some(MatchError::new(String::from("Expected type does not match found type"), + k, v + )) + } + } + None +} + diff --git a/src/storage/file/header/spec.rs b/src/storage/file/header/spec.rs new file mode 100644 index 00000000..bcec162e --- /dev/null +++ b/src/storage/file/header/spec.rs @@ -0,0 +1,41 @@ +use std::fmt::{Debug, Display, Formatter}; +use std::fmt; + +#[derive(Debug)] +#[derive(Clone)] +pub enum FileHeaderSpec { + Null, + Bool, + Integer, + UInteger, + Float, + Text, + Key { name: String, value_type: Box }, + Map { keys: Vec }, + Array { allowed_types: Vec }, +} + +impl Display for FileHeaderSpec { + + fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { + match self { + &FileHeaderSpec::Null => write!(fmt, "NULL"), + &FileHeaderSpec::Bool => write!(fmt, "Bool"), + &FileHeaderSpec::Integer => write!(fmt, "Integer"), + &FileHeaderSpec::UInteger => write!(fmt, "UInteger"), + &FileHeaderSpec::Float => write!(fmt, "Float"), + &FileHeaderSpec::Text => write!(fmt, "Text"), + &FileHeaderSpec::Key{name: ref n, value_type: ref vt} => { + write!(fmt, "Key({:?}) -> {:?}", n, vt) + } + &FileHeaderSpec::Map{keys: ref ks} => { + write!(fmt, "Map -> {:?}", ks) + } + &FileHeaderSpec::Array{allowed_types: ref at} => { + write!(fmt, "Array({:?})", at) + } + } + } + +} + diff --git a/src/storage/file/mod.rs b/src/storage/file/mod.rs index 277f7869..baa40002 100644 --- a/src/storage/file/mod.rs +++ b/src/storage/file/mod.rs @@ -5,200 +5,14 @@ use std::fmt; use regex::Regex; pub mod id; +pub mod header; use module::Module; use storage::file::id::*; use super::parser::{FileHeaderParser, Parser, ParserError}; -#[derive(Debug)] -#[derive(Clone)] -pub enum FileHeaderSpec { - Null, - Bool, - Integer, - UInteger, - Float, - Text, - Key { name: String, value_type: Box }, - Map { keys: Vec }, - Array { allowed_types: Vec }, -} - -#[derive(Debug)] -#[derive(Clone)] -pub enum FileHeaderData { - Null, - Bool(bool), - Integer(i64), - UInteger(u64), - Float(f64), - Text(String), - Key { name: String, value: Box }, - Map { keys: Vec }, - Array { values: Box> }, -} - -impl Display for FileHeaderSpec { - - fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { - match self { - &FileHeaderSpec::Null => write!(fmt, "NULL"), - &FileHeaderSpec::Bool => write!(fmt, "Bool"), - &FileHeaderSpec::Integer => write!(fmt, "Integer"), - &FileHeaderSpec::UInteger => write!(fmt, "UInteger"), - &FileHeaderSpec::Float => write!(fmt, "Float"), - &FileHeaderSpec::Text => write!(fmt, "Text"), - &FileHeaderSpec::Key{name: ref n, value_type: ref vt} => { - write!(fmt, "Key({:?}) -> {:?}", n, vt) - } - &FileHeaderSpec::Map{keys: ref ks} => { - write!(fmt, "Map -> {:?}", ks) - } - &FileHeaderSpec::Array{allowed_types: ref at} => { - write!(fmt, "Array({:?})", at) - } - } - } - -} - -impl FileHeaderData { - - pub fn matches_with(&self, r: &Regex) -> bool { - match self { - &FileHeaderData::Text(ref t) => r.is_match(&t[..]), - &FileHeaderData::Key{name: ref n, value: ref val} => { - r.is_match(n) || val.matches_with(r) - }, - - &FileHeaderData::Map{keys: ref dks} => { - dks.iter().any(|x| x.matches_with(r)) - }, - - &FileHeaderData::Array{values: ref vs} => { - vs.iter().any(|x| x.matches_with(r)) - } - - _ => false, - } - } -} - -pub struct MatchError<'a> { - summary: String, - expected: &'a FileHeaderSpec, - found: &'a FileHeaderData -} - -impl<'a> MatchError<'a> { - - pub fn new(s: String, - ex: &'a FileHeaderSpec, - found: &'a FileHeaderData) -> MatchError<'a> { - MatchError { - summary: s, - expected: ex, - found: found, - } - } - - pub fn format(&self) -> String { - format!("MatchError: {:?}\nExpected: {:?}\nFound: {:?}\n", - self.summary, self.expected, self.found) - } -} - -impl<'a> Error for MatchError<'a> { - - fn description(&self) -> &str { - &self.summary[..] - } - - fn cause(&self) -> Option<&Error> { - None - } - -} - -impl<'a> Debug for MatchError<'a> { - - fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { - write!(fmt, "{}", self.format()); - Ok(()) - } - -} - -impl<'a> Display for MatchError<'a> { - - fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { - write!(fmt, "{}", self.format()); - Ok(()) - } - -} - -pub fn match_header_spec<'a>(spec: &'a FileHeaderSpec, data: &'a FileHeaderData) - -> Option> -{ - debug!("Start matching:\n'{:?}'\non\n{:?}", spec, data); - match (spec, data) { - (&FileHeaderSpec::Null, &FileHeaderData::Null) => { } - (&FileHeaderSpec::Bool, &FileHeaderData::Bool(_)) => { } - (&FileHeaderSpec::Integer, &FileHeaderData::Integer(_)) => { } - (&FileHeaderSpec::UInteger, &FileHeaderData::UInteger(_)) => { } - (&FileHeaderSpec::Float, &FileHeaderData::Float(_)) => { } - (&FileHeaderSpec::Text, &FileHeaderData::Text(_)) => { } - - ( - &FileHeaderSpec::Key{name: ref kname, value_type: ref vtype}, - &FileHeaderData::Key{name: ref n, value: ref val} - ) => { - debug!("Matching Key: '{:?}' == '{:?}', Value: '{:?}' == '{:?}'", - kname, n, - vtype, val); - if kname != n { - debug!("Keys not matching"); - unimplemented!(); - } - return match_header_spec(&*vtype, &*val); - } - - ( - &FileHeaderSpec::Map{keys: ref sks}, - &FileHeaderData::Map{keys: ref dks} - ) => { - debug!("Matching Map: '{:?}' == '{:?}'", sks, dks); - - for (s, d) in sks.iter().zip(dks.iter()) { - let res = match_header_spec(s, d); - if res.is_some() { - return res; - } - } - } - - ( - &FileHeaderSpec::Array{allowed_types: ref vtypes}, - &FileHeaderData::Array{values: ref vs} - ) => { - debug!("Matching Array: '{:?}' == '{:?}'", vtypes, vs); - for (t, v) in vtypes.iter().zip(vs.iter()) { - let res = match_header_spec(t, v); - if res.is_some() { - return res; - } - } - } - - (k, v) => { - return Some(MatchError::new(String::from("Expected type does not match found type"), - k, v - )) - } - } - None -} +use self::header::spec::*; +use self::header::data::*; /* * Internal abstract view on a file. Does not exist on the FS and is just kept diff --git a/src/storage/json/parser.rs b/src/storage/json/parser.rs index 39b6ad58..c752e20a 100644 --- a/src/storage/json/parser.rs +++ b/src/storage/json/parser.rs @@ -8,7 +8,8 @@ use serde::ser::Serialize; use serde::ser::Serializer as Ser; use storage::parser::{FileHeaderParser, ParserError}; -use storage::file::{FileHeaderSpec, FileHeaderData}; +use storage::file::header::spec::FileHeaderSpec; +use storage::file::header::data::FileHeaderData; pub struct JsonHeaderParser { spec: Option, diff --git a/src/storage/parser.rs b/src/storage/parser.rs index 0f30f04b..c627e56a 100644 --- a/src/storage/parser.rs +++ b/src/storage/parser.rs @@ -4,7 +4,7 @@ use std::fmt; use regex::Regex; -use super::file::FileHeaderData; +use super::file::header::data::FileHeaderData; pub struct ParserError { summary: String,