actiondb 0.3.0

A safe and efficient unstructured text (log) parsing library.
use std::hash::{SipHasher, Hash, Hasher};
use super::{ParserBase, Parser, ObjectSafeHash, ParseResult};

#[derive(Clone, Debug, Hash)]
pub struct GreedyParser {
    base: ParserBase,
    end_string: Option<String>
}

impl GreedyParser {
    pub fn with_name(name: String) -> GreedyParser {
        GreedyParser{ base: ParserBase::with_name(name),
                       end_string: None }
    }

    pub fn from_str(name: &str, end_string: &str) -> GreedyParser {
        let mut parser = GreedyParser::with_name(name.to_string());
        parser.set_end_string(end_string.to_string());
        parser
    }

    pub fn new() -> GreedyParser {
        GreedyParser {
            base: ParserBase::new(),
            end_string: None
        }
    }

    pub fn set_end_string(&mut self, end_string: String) {
        self.end_string = Some(end_string);
    }
}

impl ObjectSafeHash for GreedyParser {
    fn hash_os(&self) -> u64 {
        let mut hasher = SipHasher::new();
        "parser:greedy".hash(&mut hasher);
        self.hash(&mut hasher);
        hasher.finish()
    }
}

impl Parser for GreedyParser {
    fn parse<'a, 'b>(&'a self, value: &'b str) -> Option<ParseResult<'a, 'b>> {
        if self.end_string.is_none() {
            return Some(ParseResult::new(self, &value[..]))
        }

        if let Some(pos) = value.find(&self.end_string.as_ref().unwrap()[..]) {
            Some(ParseResult::new(self, &value[..pos]))
        } else {
            None
        }
    }

    fn name(&self) -> Option<&str> {
        self.base.name()
    }

    fn set_name(&mut self, name: Option<String>) {
        self.base.set_name(name);
    }

    fn boxed_clone(&self) -> Box<Parser> {
        Box::new(self.clone())
    }
}

#[cfg(test)]
mod test {
    use parsers::{GreedyParser, Parser};

    #[test]
    fn test_given_greedy_parser_when_the_end_string_is_not_found_in_the_value_then_the_parser_doesnt_match() {
        let parser = GreedyParser::from_str("name", "foo");
        assert_eq!(parser.parse("qux baz bar").is_none(), true);
    }

    #[test]
    fn test_given_greedy_parser_when_the_end_string_is_found_in_the_value_then_the_parser_matches() {
        let parser = GreedyParser::from_str("name", "foo");
        let res = parser.parse("qux foo bar").unwrap();
        assert_eq!(res.parser().name(), Some("name"));
        assert_eq!(res.value(), "qux ");
    }
}