Fully replaced conditional's Container type with ParameterizedBlock.

This commit is contained in:
Tom Alexander 2020-05-25 21:26:16 -04:00
parent dc92973313
commit 108cffb771
Signed by: talexander
GPG Key ID: D3A179C9A53C0EDE

View File

@ -29,9 +29,9 @@ pub enum DustTag<'a> {
DTComment(Comment<'a>),
DTLiteralStringBlock(&'a str),
DTReference(Reference<'a>),
DTSection(Container<'a>),
DTExists(Container<'a>),
DTNotExists(Container<'a>),
DTSection(ParameterizedBlock<'a>),
DTExists(ParameterizedBlock<'a>),
DTNotExists(ParameterizedBlock<'a>),
DTBlock(NamedBlock<'a>),
DTInlinePartial(NamedBlock<'a>),
DTPartial(Partial<'a>),
@ -92,14 +92,6 @@ pub struct Span<'a> {
pub contents: &'a str,
}
#[derive(Clone, Debug, PartialEq)]
pub struct Container<'a> {
pub path: Path<'a>,
pub explicit_context: Option<Path<'a>>,
pub contents: Option<Body<'a>>,
pub else_contents: Option<Body<'a>>,
}
#[derive(Clone, Debug, PartialEq)]
pub struct NamedBlock<'a> {
pub name: &'a str,
@ -218,9 +210,9 @@ fn dust_tag(i: &str) -> IResult<&str, DustTag> {
map(comment, DustTag::DTComment),
map(literal_string_block, DustTag::DTLiteralStringBlock),
map(reference, DustTag::DTReference),
conditional("{#", DustTag::DTSection),
conditional("{?", DustTag::DTExists),
conditional("{^", DustTag::DTNotExists),
map(parameterized_block("{#", path), DustTag::DTSection),
map(parameterized_block("{?", path), DustTag::DTExists),
map(parameterized_block("{^", path), DustTag::DTNotExists),
named_block("{+", DustTag::DTBlock),
named_block("{<", DustTag::DTInlinePartial),
partial("{>", DustTag::DTPartial),
@ -350,76 +342,6 @@ fn reference(i: &str) -> IResult<&str, Reference> {
))
}
fn conditional<'a, F>(
open_matcher: &'static str,
constructor: F,
) -> impl FnMut(&'a str) -> IResult<&'a str, DustTag<'a>>
where
F: Copy + Fn(Container<'a>) -> DustTag<'a>,
{
alt((
conditional_with_body(open_matcher, constructor),
self_closing_conditional(open_matcher, constructor),
))
}
fn conditional_with_body<'a, F>(
open_matcher: &'static str,
constructor: F,
) -> impl Fn(&'a str) -> IResult<&'a str, DustTag<'a>>
where
F: Fn(Container<'a>) -> DustTag<'a>,
{
move |i: &'a str| {
let (i, (opening_name, maybe_explicit_context, inner, maybe_else, _closing_name)) =
verify(
tuple((
preceded(tag(open_matcher), path),
terminated(opt(preceded(tag(":"), path)), tag("}")),
opt(body),
opt(preceded(tag("{:else}"), opt(body))),
delimited(tag("{/"), path, tag("}")),
)),
|(open, _maybe_explicit, _inn, _maybe_else, close)| open == close,
)(i)?;
Ok((
i,
constructor(Container {
path: opening_name,
explicit_context: maybe_explicit_context,
contents: inner,
else_contents: maybe_else.flatten(),
}),
))
}
}
fn self_closing_conditional<'a, F>(
open_matcher: &'static str,
constructor: F,
) -> impl Fn(&'a str) -> IResult<&'a str, DustTag<'a>>
where
F: Fn(Container<'a>) -> DustTag<'a>,
{
move |i: &'a str| {
let (i, (opening_name, maybe_explicit_context)) = tuple((
preceded(tag(open_matcher), path),
terminated(opt(preceded(tag(":"), path)), tag("/}")),
))(i)?;
Ok((
i,
constructor(Container {
path: opening_name,
explicit_context: maybe_explicit_context,
contents: None,
else_contents: None,
}),
))
}
}
fn named_block<'a, F>(
open_matcher: &'static str,
constructor: F,
@ -920,11 +842,12 @@ mod tests {
super::dust_tag("{#foo.bar}{/foo.bar}"),
Ok((
"",
DustTag::DTSection(Container {
DustTag::DTSection(ParameterizedBlock {
path: Path {
keys: vec!["foo", "bar"]
},
explicit_context: None,
params: Vec::new(),
contents: None,
else_contents: None,
})
@ -938,11 +861,12 @@ mod tests {
super::dust_tag("{#foo.bar/}"),
Ok((
"",
DustTag::DTSection(Container {
DustTag::DTSection(ParameterizedBlock {
path: Path {
keys: vec!["foo", "bar"]
},
explicit_context: None,
params: Vec::new(),
contents: None,
else_contents: None,
})
@ -956,11 +880,12 @@ mod tests {
super::dust_tag("{#foo.bar}hello {name}{/foo.bar}"),
Ok((
"",
DustTag::DTSection(Container {
DustTag::DTSection(ParameterizedBlock {
path: Path {
keys: vec!["foo", "bar"]
},
explicit_context: None,
params: Vec::new(),
contents: Some(Body {
elements: vec![
TemplateElement::TESpan(Span { contents: "hello " }),
@ -982,11 +907,12 @@ mod tests {
super::dust_tag("{#greeting}hello {name}{:else}goodbye {name}{/greeting}"),
Ok((
"",
DustTag::DTSection(Container {
DustTag::DTSection(ParameterizedBlock {
path: Path {
keys: vec!["greeting"]
},
explicit_context: None,
params: Vec::new(),
contents: Some(Body {
elements: vec![
TemplateElement::TESpan(Span { contents: "hello " }),
@ -1018,13 +944,14 @@ mod tests {
super::dust_tag("{#foo.bar:baz.ipsum}{/foo.bar}"),
Ok((
"",
DustTag::DTSection(Container {
DustTag::DTSection(ParameterizedBlock {
path: Path {
keys: vec!["foo", "bar"]
},
explicit_context: Some(Path {
keys: vec!["baz", "ipsum"]
}),
params: Vec::new(),
contents: None,
else_contents: None,
})
@ -1038,11 +965,12 @@ mod tests {
super::dust_tag("{#foo.bar:$idx/}"),
Ok((
"",
DustTag::DTSection(Container {
DustTag::DTSection(ParameterizedBlock {
path: Path {
keys: vec!["foo", "bar"]
},
explicit_context: Some(Path { keys: vec!["$idx"] }),
params: Vec::new(),
contents: None,
else_contents: None,
})
@ -1500,11 +1428,12 @@ mod tests {
TemplateElement::TEIgnoredWhitespace(IgnoredWhitespace::StartOfLine(
"\n"
)),
TemplateElement::TETag(DustTag::DTSection(Container {
TemplateElement::TETag(DustTag::DTSection(ParameterizedBlock {
path: Path {
keys: vec!["names"]
},
explicit_context: None,
params: Vec::new(),
contents: Some(Body {
elements: vec![TemplateElement::TETag(DustTag::DTReference(
Reference {
@ -1526,11 +1455,12 @@ mod tests {
TemplateElement::TEIgnoredWhitespace(IgnoredWhitespace::StartOfLine(
"\n"
)),
TemplateElement::TETag(DustTag::DTSection(Container {
TemplateElement::TETag(DustTag::DTSection(ParameterizedBlock {
path: Path {
keys: vec!["names"]
},
explicit_context: None,
params: Vec::new(),
contents: Some(Body {
elements: vec![
TemplateElement::TEIgnoredWhitespace(
@ -1564,55 +1494,58 @@ mod tests {
"",
Template {
contents: Body {
elements: vec![TemplateElement::TETag(DustTag::DTSection(Container {
path: Path {
keys: vec!["level3", "level4"]
},
explicit_context: None,
contents: Some(Body {
elements: vec![TemplateElement::TETag(DustTag::DTPartial(
Partial {
name: vec![PartialNameElement::PNSpan {
contents: "partialtwo".to_owned()
},],
explicit_context: None,
params: vec![
KVPair {
key: "v1",
value: RValue::RVLiteral(OwnedLiteral::LString(
"b".to_owned()
))
},
KVPair {
key: "v2",
value: RValue::RVLiteral(OwnedLiteral::LString(
"b".to_owned()
))
},
KVPair {
key: "v3",
value: RValue::RVLiteral(OwnedLiteral::LString(
"b".to_owned()
))
},
KVPair {
key: "v4",
value: RValue::RVLiteral(OwnedLiteral::LString(
"b".to_owned()
))
},
KVPair {
key: "v5",
value: RValue::RVLiteral(OwnedLiteral::LString(
"b".to_owned()
))
}
]
}
))]
}),
else_contents: None
}))]
elements: vec![TemplateElement::TETag(DustTag::DTSection(
ParameterizedBlock {
path: Path {
keys: vec!["level3", "level4"]
},
explicit_context: None,
params: Vec::new(),
contents: Some(Body {
elements: vec![TemplateElement::TETag(DustTag::DTPartial(
Partial {
name: vec![PartialNameElement::PNSpan {
contents: "partialtwo".to_owned()
},],
explicit_context: None,
params: vec![
KVPair {
key: "v1",
value: RValue::RVLiteral(
OwnedLiteral::LString("b".to_owned())
)
},
KVPair {
key: "v2",
value: RValue::RVLiteral(
OwnedLiteral::LString("b".to_owned())
)
},
KVPair {
key: "v3",
value: RValue::RVLiteral(
OwnedLiteral::LString("b".to_owned())
)
},
KVPair {
key: "v4",
value: RValue::RVLiteral(
OwnedLiteral::LString("b".to_owned())
)
},
KVPair {
key: "v5",
value: RValue::RVLiteral(
OwnedLiteral::LString("b".to_owned())
)
}
]
}
))]
}),
else_contents: None
}
))]
}
}
))