tpl 0.1.4

simple pure template
Documentation
use std::str;
use nom::IResult;
use errors::{Error, ErrorKind};

#[derive(Debug, PartialEq)]
pub enum Exp<'a> {
    Func { name: &'a str },
    Literal(&'a str),
}

named!(literal<&[u8], Exp>,
    map!(
        map_res!(
            is_not!("%{"),
            str::from_utf8
        ),
        Exp::Literal
    )
);

named!(func<&[u8], Exp>,
    do_parse!(
        tag!("%{") >>
        name: map_res!(take_until!("}"), str::from_utf8) >>
        tag!("}") >>
        (Exp::Func {
            name: name,
        })
    )
);

named!(pub exps<&[u8], Vec<Exp>>,
    many0!(
        alt!(func | literal)
    )
);

pub fn parse(input: &str) -> Result<Vec<Exp>, Error> {
    match exps(input.as_bytes()) {
        IResult::Done(_, exps) => Ok(exps),
        _ => Err(ErrorKind::Parse.into()),
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn parse_literal() {
        assert_eq!(
            literal(b"testing"),
            IResult::Done(&b""[..], Exp::Literal("testing"))
        );
    }

    #[test]
    fn parse_func() {
        assert_eq!(
            func(b"%{test}"),
            IResult::Done(&b""[..], Exp::Func { name: "test" })
        );
    }

    #[test]
    fn parse_exps() {
        assert_eq!(
            exps(b"%{test}literal%{test2}haha"),
            IResult::Done(
                &b""[..],
                vec![
                    Exp::Func { name: "test" },
                    Exp::Literal("literal"),
                    Exp::Func { name: "test2" },
                    Exp::Literal("haha"),
                ],
            )
        );

        assert_eq!(
            exps(b"haha%{test}%{test2}lala"),
            IResult::Done(
                &b""[..],
                vec![
                    Exp::Literal("haha"),
                    Exp::Func { name: "test" },
                    Exp::Func { name: "test2" },
                    Exp::Literal("lala"),
                ],
            )
        );
    }
}