Cleaning up and factoring out reused code in the renderer.

This commit is contained in:
Tom Alexander 2020-05-16 17:17:43 -04:00
parent 0f90fa2c7e
commit b53a9e1837
Signed by: talexander
GPG Key ID: D3A179C9A53C0EDE

View File

@ -77,6 +77,18 @@ impl<'a> DustRenderer<'a> {
self.render_body(&main_template.contents, breadcrumbs, &new_blocks)
}
fn render_maybe_body(
&'a self,
body: &'a Option<Body>,
breadcrumbs: &Vec<&'a dyn ContextElement>,
blocks: &'a InlinePartialTreeElement<'a>,
) -> Result<String, RenderError> {
match body {
None => Ok("".to_owned()),
Some(body) => Ok(self.render_body(body, breadcrumbs, blocks)?),
}
}
fn render_body(
&'a self,
body: &'a Body,
@ -130,16 +142,13 @@ impl<'a> DustRenderer<'a> {
}
DustTag::DTSection(container) => {
let val = walk_path(breadcrumbs, &container.path.keys);
let loop_elements: Vec<&dyn ContextElement> = self.get_loop_elements(val);
let loop_elements: Vec<&dyn ContextElement> = Self::get_loop_elements(val);
if loop_elements.is_empty() {
// Oddly enough if the value is falsey (like
// an empty array or null), Dust uses the
// original context before walking the path as
// the context for rendering the else block
return match &container.else_contents {
Some(body) => self.render_body(&body, breadcrumbs, blocks),
None => Ok("".to_owned()),
};
return self.render_maybe_body(&container.else_contents, breadcrumbs, blocks);
} else {
match &container.contents {
None => return Ok("".to_owned()),
@ -160,33 +169,21 @@ impl<'a> DustRenderer<'a> {
}
DustTag::DTExists(container) => {
let val = walk_path(breadcrumbs, &container.path.keys);
let loop_elements: Vec<&dyn ContextElement> = self.get_loop_elements(val);
if loop_elements.is_empty() {
return match &container.else_contents {
Some(body) => self.render_body(&body, breadcrumbs, blocks),
None => Ok("".to_owned()),
};
let loop_elements: Vec<&dyn ContextElement> = Self::get_loop_elements(val);
return if loop_elements.is_empty() {
self.render_maybe_body(&container.else_contents, breadcrumbs, blocks)
} else {
return match &container.contents {
None => Ok("".to_owned()),
Some(body) => self.render_body(&body, breadcrumbs, blocks),
};
}
self.render_maybe_body(&container.contents, breadcrumbs, blocks)
};
}
DustTag::DTNotExists(container) => {
let val = walk_path(breadcrumbs, &container.path.keys);
let loop_elements: Vec<&dyn ContextElement> = self.get_loop_elements(val);
if !loop_elements.is_empty() {
return match &container.else_contents {
Some(body) => self.render_body(&body, breadcrumbs, blocks),
None => Ok("".to_owned()),
};
let loop_elements: Vec<&dyn ContextElement> = Self::get_loop_elements(val);
return if !loop_elements.is_empty() {
self.render_maybe_body(&container.else_contents, breadcrumbs, blocks)
} else {
return match &container.contents {
None => Ok("".to_owned()),
Some(body) => self.render_body(&body, breadcrumbs, blocks),
};
}
self.render_maybe_body(&container.contents, breadcrumbs, blocks)
};
}
DustTag::DTPartial(partial) => {
if partial.params.is_empty() {
@ -202,34 +199,19 @@ impl<'a> DustRenderer<'a> {
return Ok(rendered_content);
}
}
DustTag::DTInlinePartial(named_block) => {
DustTag::DTInlinePartial(_named_block) => {
// Inline partials are blank during rendering (they get injected into blocks)
return Ok("".to_owned());
}
DustTag::DTBlock(named_block) => {
match blocks.get_block(named_block.name) {
None => match &named_block.contents {
None => return Ok("".to_owned()),
Some(body) => {
let rendered_content = self.render_body(body, breadcrumbs, blocks)?;
return Ok(rendered_content);
}
},
Some(interior) => match interior {
None => return Ok("".to_owned()),
Some(body) => {
let rendered_content = self.render_body(body, breadcrumbs, blocks)?;
return Ok(rendered_content);
}
},
return match blocks.get_block(named_block.name) {
None => self.render_maybe_body(&named_block.contents, breadcrumbs, blocks),
Some(interior) => self.render_maybe_body(interior, breadcrumbs, blocks),
};
}
DustTag::DTHelperEquals(parameterized_block) => {
let param_map: HashMap<&str, &RValue<'a>> = parameterized_block
.params
.iter()
.map(|pair: &KVPair<'a>| (pair.key, &pair.value))
.collect();
let param_map: HashMap<&str, &RValue<'a>> =
Self::get_rval_map(&parameterized_block.params);
// Special case: when comparing two RVPaths, if the
// path is equal then dust assumes the values are
// equal (otherwise, non-scalar values are
@ -244,47 +226,31 @@ impl<'a> DustRenderer<'a> {
};
}
let left_side: Result<&dyn ContextElement, WalkError> = match param_map.get("key") {
None => return Ok("".to_owned()),
Some(rval) => match rval {
RValue::RVString(text) => Ok(text),
RValue::RVPath(path) => walk_path(breadcrumbs, &path.keys),
RValue::RVPositiveInteger(num) => Ok(num),
},
};
let right_side: Result<&dyn ContextElement, WalkError> =
match param_map.get("value") {
None => Err(WalkError::CantWalk),
Some(rval) => match rval {
RValue::RVString(text) => Ok(text),
RValue::RVPath(path) => walk_path(breadcrumbs, &path.keys),
RValue::RVPositiveInteger(num) => Ok(num),
},
let left_side: Result<&dyn ContextElement, WalkError> =
match Self::get_rval(breadcrumbs, &param_map, "key") {
None => return Ok("".to_owned()),
Some(res) => res,
};
let right_side: Result<&dyn ContextElement, WalkError> =
Self::get_rval(breadcrumbs, &param_map, "value")
.unwrap_or(Err(WalkError::CantWalk));
if left_side == right_side {
match &parameterized_block.contents {
None => return Ok("".to_owned()),
Some(body) => {
let rendered_content = self.render_body(body, breadcrumbs, blocks)?;
return Ok(rendered_content);
}
}
return self.render_maybe_body(
&parameterized_block.contents,
breadcrumbs,
blocks,
);
} else {
match &parameterized_block.else_contents {
None => return Ok("".to_owned()),
Some(body) => {
let rendered_content = self.render_body(body, breadcrumbs, blocks)?;
return Ok(rendered_content);
}
}
return self.render_maybe_body(
&parameterized_block.else_contents,
breadcrumbs,
blocks,
);
}
}
DustTag::DTHelperNotEquals(parameterized_block) => {
let param_map: HashMap<&str, &RValue<'a>> = parameterized_block
.params
.iter()
.map(|pair: &KVPair<'a>| (pair.key, &pair.value))
.collect();
let param_map: HashMap<&str, &RValue<'a>> =
Self::get_rval_map(&parameterized_block.params);
// Special case: when comparing two RVPaths, if the
// path is equal then dust assumes the values are
// equal (otherwise, non-scalar values are
@ -299,64 +265,39 @@ impl<'a> DustRenderer<'a> {
};
}
let left_side: Result<&dyn ContextElement, WalkError> = match param_map.get("key") {
None => return Ok("".to_owned()),
Some(rval) => match rval {
RValue::RVString(text) => Ok(text),
RValue::RVPath(path) => walk_path(breadcrumbs, &path.keys),
RValue::RVPositiveInteger(num) => Ok(num),
},
};
let right_side: Result<&dyn ContextElement, WalkError> =
match param_map.get("value") {
None => Err(WalkError::CantWalk),
Some(rval) => match rval {
RValue::RVString(text) => Ok(text),
RValue::RVPath(path) => walk_path(breadcrumbs, &path.keys),
RValue::RVPositiveInteger(num) => Ok(num),
},
let left_side: Result<&dyn ContextElement, WalkError> =
match Self::get_rval(breadcrumbs, &param_map, "key") {
None => return Ok("".to_owned()),
Some(res) => res,
};
let right_side: Result<&dyn ContextElement, WalkError> =
Self::get_rval(breadcrumbs, &param_map, "value")
.unwrap_or(Err(WalkError::CantWalk));
if left_side != right_side {
match &parameterized_block.contents {
None => return Ok("".to_owned()),
Some(body) => {
let rendered_content = self.render_body(body, breadcrumbs, blocks)?;
return Ok(rendered_content);
}
}
return self.render_maybe_body(
&parameterized_block.contents,
breadcrumbs,
blocks,
);
} else {
match &parameterized_block.else_contents {
None => return Ok("".to_owned()),
Some(body) => {
let rendered_content = self.render_body(body, breadcrumbs, blocks)?;
return Ok(rendered_content);
}
}
return self.render_maybe_body(
&parameterized_block.else_contents,
breadcrumbs,
blocks,
);
}
}
DustTag::DTHelperGreaterThan(parameterized_block) => {
let param_map: HashMap<&str, &RValue<'a>> = parameterized_block
.params
.iter()
.map(|pair: &KVPair<'a>| (pair.key, &pair.value))
.collect();
let left_side: Result<&dyn ContextElement, WalkError> = match param_map.get("key") {
None => return Ok("".to_owned()),
Some(rval) => match rval {
RValue::RVString(text) => Ok(text),
RValue::RVPath(path) => walk_path(breadcrumbs, &path.keys),
RValue::RVPositiveInteger(num) => Ok(num),
},
};
let right_side: Result<&dyn ContextElement, WalkError> =
match param_map.get("value") {
None => Err(WalkError::CantWalk),
Some(rval) => match rval {
RValue::RVString(text) => Ok(text),
RValue::RVPath(path) => walk_path(breadcrumbs, &path.keys),
RValue::RVPositiveInteger(num) => Ok(num),
},
let param_map: HashMap<&str, &RValue<'a>> =
Self::get_rval_map(&parameterized_block.params);
let left_side: Result<&dyn ContextElement, WalkError> =
match Self::get_rval(breadcrumbs, &param_map, "key") {
None => return Ok("".to_owned()),
Some(res) => res,
};
let right_side: Result<&dyn ContextElement, WalkError> =
Self::get_rval(breadcrumbs, &param_map, "value")
.unwrap_or(Err(WalkError::CantWalk));
match (left_side, right_side) {
(Err(_), _) | (_, Err(_)) => match &parameterized_block.else_contents {
None => return Ok("".to_owned()),
@ -367,23 +308,17 @@ impl<'a> DustRenderer<'a> {
},
(Ok(left_side_unwrapped), Ok(right_side_unwrapped)) => {
if left_side_unwrapped > right_side_unwrapped {
match &parameterized_block.contents {
None => return Ok("".to_owned()),
Some(body) => {
let rendered_content =
self.render_body(body, breadcrumbs, blocks)?;
return Ok(rendered_content);
}
}
return self.render_maybe_body(
&parameterized_block.contents,
breadcrumbs,
blocks,
);
} else {
match &parameterized_block.else_contents {
None => return Ok("".to_owned()),
Some(body) => {
let rendered_content =
self.render_body(body, breadcrumbs, blocks)?;
return Ok(rendered_content);
}
}
return self.render_maybe_body(
&parameterized_block.else_contents,
breadcrumbs,
blocks,
);
}
}
}
@ -398,7 +333,6 @@ impl<'a> DustRenderer<'a> {
/// If the value is falsey, and therefore should render the else
/// block, this will return an empty vector.
fn get_loop_elements<'b>(
&'a self,
walk_result: Result<&'b dyn ContextElement, WalkError>,
) -> Vec<&'b dyn ContextElement> {
match walk_result {
@ -419,6 +353,28 @@ impl<'a> DustRenderer<'a> {
},
}
}
fn get_rval_map<'b>(params: &'b Vec<KVPair<'b>>) -> HashMap<&'b str, &'b RValue<'b>> {
params
.iter()
.map(|pair: &KVPair<'b>| (pair.key, &pair.value))
.collect()
}
fn get_rval<'b>(
breadcrumbs: &Vec<&'b dyn ContextElement>,
param_map: &HashMap<&str, &'b RValue<'b>>,
key: &str,
) -> Option<Result<&'b dyn ContextElement, WalkError>> {
match param_map.get(key) {
None => None,
Some(rval) => match rval {
RValue::RVString(text) => Some(Ok(text)),
RValue::RVPath(path) => Some(walk_path(breadcrumbs, &path.keys)),
RValue::RVPositiveInteger(num) => Some(Ok(num)),
},
}
}
}
#[cfg(test)]