Builder style, lazy evaluating matcher.
#[macro_use] extern crate must;
use must::prelude::*;
#[derive(Debug, PartialEq)]
pub enum Lit {
Num(i64),
Bool(bool),
}
#[derive(Debug)]
pub struct ParseError;
pub fn parse_lit(i: &str) -> Result<Lit, ParseError> {
if i == "true" {
Ok(Lit::Bool(true))
} else if i == "false" {
Ok(Lit::Bool(false))
} else {
Ok(Lit::Num(i.parse().expect("not a number?")))
}
}
use std::fmt::Debug;
use must::Mutator;
use must::LazyAssertion;
use must::LazyMatcher;
pub trait ParserMust<T: Debug + PartialEq> {
fn must_parse(self, s: &str) -> LazyAssertion<ParseAs<T>>;
}
impl<T: Debug + PartialEq> ParserMust<T> for fn(&str) -> Result<T, ParseError> {
fn must_parse(self, s: &str) -> LazyAssertion<ParseAs<T>> {
LazyAssertion::from(ParseAs {
parser: self,
data: s.to_owned(),
want: None,
})
}
}
pub struct ParseAs<T: Debug + PartialEq> {
parser: fn(&str) -> Result<T, ParseError>,
data: String,
want: Option<T>,
}
pub trait ParseAsBuilder<T: Debug + PartialEq> : Mutator<ParseAs<T>> {
fn as_ok(self, t: T) -> Self {
self.mutate(|l| l.want = Some(t))
}
}
impl<T: Debug + PartialEq, M> ParseAsBuilder<T> for M where M: Mutator<ParseAs<T>> {}
impl<T: Debug + PartialEq> LazyMatcher for ParseAs<T> {
type Ret = ();
fn test(self) -> Result<Self::Ret, MustError> {
let want = match self.want {
Some(want) => want,
None => panic!("ParseAs.to() is not called."),
};
let result = (self.parser)(&self.data);
result.must_be_ok_and(|val| {
val.must_be(want)
}).into_result().map(|_| ())
}
}
let parser: fn(&str) -> Result<Lit, ParseError> = parse_lit;
parser.must_parse("false").as_ok(Lit::Bool(false));
parser.must_parse("true").as_ok(Lit::Bool(true)).or(fail!());
parser.must_parse("352").as_ok(Lit::Num(352)).or(fail!());