2020-04-05 00:16:44 +00:00
|
|
|
use nom::branch::alt;
|
2020-04-05 00:37:35 +00:00
|
|
|
use nom::bytes::complete::is_a;
|
2020-04-05 00:16:44 +00:00
|
|
|
use nom::bytes::complete::tag;
|
|
|
|
use nom::bytes::complete::take_until;
|
|
|
|
use nom::combinator::map;
|
2020-04-05 00:37:35 +00:00
|
|
|
use nom::combinator::recognize;
|
2020-04-05 00:16:44 +00:00
|
|
|
use nom::combinator::value;
|
2020-04-05 00:51:10 +00:00
|
|
|
use nom::multi::many0;
|
2020-04-05 00:37:35 +00:00
|
|
|
use nom::multi::separated_list;
|
2020-04-05 00:16:44 +00:00
|
|
|
use nom::sequence::delimited;
|
2020-04-05 00:51:10 +00:00
|
|
|
use nom::sequence::preceded;
|
2020-04-05 00:37:35 +00:00
|
|
|
use nom::sequence::tuple;
|
2020-04-05 00:16:44 +00:00
|
|
|
use nom::IResult;
|
|
|
|
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
enum DustTag<'a> {
|
|
|
|
DTSpecial(Special),
|
|
|
|
DTComment(Comment<'a>),
|
2020-04-05 00:37:35 +00:00
|
|
|
DTReference(Reference<'a>),
|
2020-04-05 00:16:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
enum Special {
|
|
|
|
Space,
|
|
|
|
NewLine,
|
|
|
|
CarriageReturn,
|
|
|
|
LeftCurlyBrace,
|
|
|
|
RightCurlyBrace,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
struct Comment<'a> {
|
|
|
|
value: &'a str,
|
|
|
|
}
|
|
|
|
|
2020-04-05 00:37:35 +00:00
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
struct Path<'a> {
|
|
|
|
keys: Vec<&'a str>,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
struct Reference<'a> {
|
|
|
|
path: Path<'a>,
|
2020-04-05 00:51:10 +00:00
|
|
|
filters: Vec<Filter>,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
enum Filter {
|
|
|
|
HtmlEncode,
|
|
|
|
DisableHtmlEncode,
|
|
|
|
JavascriptStringEncode,
|
|
|
|
EncodeUri,
|
|
|
|
EncodeUriComponent,
|
|
|
|
JsonStringify,
|
|
|
|
JsonParse,
|
2020-04-05 00:37:35 +00:00
|
|
|
}
|
|
|
|
|
2020-04-05 00:16:44 +00:00
|
|
|
fn dust_tag(i: &str) -> IResult<&str, DustTag> {
|
|
|
|
alt((
|
|
|
|
map(special, DustTag::DTSpecial),
|
|
|
|
map(comment, DustTag::DTComment),
|
2020-04-05 00:37:35 +00:00
|
|
|
map(reference, DustTag::DTReference),
|
2020-04-05 00:16:44 +00:00
|
|
|
))(i)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn special(i: &str) -> IResult<&str, Special> {
|
|
|
|
delimited(
|
|
|
|
tag("{~"),
|
|
|
|
alt((
|
|
|
|
value(Special::Space, tag("s")),
|
|
|
|
value(Special::NewLine, tag("s")),
|
|
|
|
value(Special::CarriageReturn, tag("s")),
|
|
|
|
value(Special::LeftCurlyBrace, tag("s")),
|
|
|
|
value(Special::RightCurlyBrace, tag("s")),
|
|
|
|
)),
|
|
|
|
tag("}"),
|
|
|
|
)(i)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn comment(i: &str) -> IResult<&str, Comment> {
|
|
|
|
map(delimited(tag("{!"), take_until("!}"), tag("!}")), |body| {
|
|
|
|
Comment { value: body }
|
|
|
|
})(i)
|
|
|
|
}
|
2020-04-05 00:37:35 +00:00
|
|
|
|
|
|
|
fn path(i: &str) -> IResult<&str, Path> {
|
|
|
|
map(
|
|
|
|
separated_list(
|
|
|
|
tag("."),
|
|
|
|
recognize(tuple((
|
|
|
|
is_a("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_$"),
|
|
|
|
is_a("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_$0123456789-"),
|
|
|
|
))),
|
|
|
|
),
|
|
|
|
|body| Path { keys: body },
|
|
|
|
)(i)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn reference(i: &str) -> IResult<&str, Reference> {
|
2020-04-05 00:51:10 +00:00
|
|
|
let (remaining, (p, filters)) = delimited(tag("{"), tuple((path, many0(filter))), tag("}"))(i)?;
|
|
|
|
Ok((
|
|
|
|
remaining,
|
|
|
|
Reference {
|
|
|
|
path: p,
|
|
|
|
filters: filters,
|
|
|
|
},
|
|
|
|
))
|
|
|
|
}
|
|
|
|
|
|
|
|
fn filter(i: &str) -> IResult<&str, Filter> {
|
|
|
|
preceded(
|
|
|
|
tag("|"),
|
|
|
|
alt((
|
|
|
|
value(Filter::JsonStringify, tag("js")),
|
|
|
|
value(Filter::JsonParse, tag("jp")),
|
|
|
|
value(Filter::EncodeUriComponent, tag("uc")),
|
|
|
|
value(Filter::HtmlEncode, tag("h")),
|
|
|
|
value(Filter::DisableHtmlEncode, tag("s")),
|
|
|
|
value(Filter::JavascriptStringEncode, tag("j")),
|
|
|
|
value(Filter::EncodeUri, tag("u")),
|
|
|
|
)),
|
|
|
|
)(i)
|
2020-04-05 00:37:35 +00:00
|
|
|
}
|