Module must::lazy [] [src]

Builder style, lazy evaluating matcher.

Examples (extending)

#[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> {
    // showcase..
    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?")))
    }
}

// and in your test,
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,
        })
    }
}

// Mutator<ParseAs<T>> is implemented for ParseAs<T> (as logically it is mutator)
pub struct ParseAs<T: Debug + PartialEq> {
    parser: fn(&str) -> Result<T, ParseError>,
    // let's use owned type, to avoid adding a lifetime parameter.
    data: String,
    // Used Option because it will be filled in later call.
    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() returns LazyAssertion
            val.must_be(want)
        }).into_result().map(|_| ())  // std::result::Result has map method
    }
}

// in #[test] function
// auto coercion for fn type is sometimes strange.
let parser: fn(&str) -> Result<Lit, ParseError> = parse_lit;
parser.must_parse("false").as_ok(Lit::Bool(false)); // .or(fail!()) is optional
parser.must_parse("true").as_ok(Lit::Bool(true)).or(fail!());
parser.must_parse("352").as_ok(Lit::Num(352)).or(fail!());

// You can change type of ParseAs.want to Option<Result<T, ParseError>>
// and add function like as_err(expected) (optionaly with validation logic).
// And you might add function like with_rem(remain: &str)

Structs

LazyAssertion
SimpleMatcher

Traits

LazyMatcher

Matcher holds 'got'

Type Definitions

SimpleAssert