Put IntoContextElement everywhere. It compiles again.

master
Tom Alexander 4 years ago
parent 975ab278ef
commit 917da5a073
Signed by: talexander
GPG Key ID: D3A179C9A53C0EDE

@ -49,3 +49,7 @@ Reference Parameters{~n}
Hello {name}, nice {pet}{~n}
{/other_petname}
{/people}
{! Can you go through multiple levels of references !}
{#truthy name="chris" pet="{petname}" petname="{deeperpetname}" deeperpetname="fluffy"}
Hello {name}, nice {pet}{~n}
{/truthy}

@ -7,6 +7,7 @@ use renderer::compile_template;
use renderer::CompiledTemplate;
use renderer::ContextElement;
use renderer::DustRenderer;
use renderer::IntoContextElement;
use renderer::Loopable;
use renderer::RenderError;
use renderer::Renderable;
@ -49,7 +50,7 @@ fn main() {
.first()
.expect("There should be more than 1 template")
.name;
let breadcrumbs = vec![&context as &dyn ContextElement];
let breadcrumbs = vec![&context as &dyn IntoContextElement];
println!(
"{}",
dust_renderer
@ -276,7 +277,7 @@ impl Renderable for serde_json::Value {
}
impl Walkable for serde_json::Value {
fn walk(&self, segment: &str) -> Result<&dyn ContextElement, WalkError> {
fn walk(&self, segment: &str) -> Result<&dyn IntoContextElement, WalkError> {
match self {
serde_json::Value::Null => Err(WalkError::CantWalk),
serde_json::Value::Bool(_boolean) => Err(WalkError::CantWalk),

@ -21,7 +21,7 @@ pub trait Truthiness {
}
pub trait Walkable {
fn walk(&self, segment: &str) -> Result<&dyn ContextElement, WalkError>;
fn walk(&self, segment: &str) -> Result<&dyn IntoContextElement, WalkError>;
/// If an element contains meta information and should not be
/// returned as the final result of a walk, this function should
@ -61,11 +61,11 @@ pub trait CompareContextElement: CastToAny {
}
pub trait CloneIntoBoxedContextElement {
fn clone_to_box(&self) -> Box<dyn ContextElement>;
fn clone_to_box(&self) -> Box<dyn IntoContextElement>;
}
impl<C: 'static + ContextElement + Clone> CloneIntoBoxedContextElement for C {
fn clone_to_box(&self) -> Box<dyn ContextElement> {
impl<C: 'static + IntoContextElement + Clone> CloneIntoBoxedContextElement for C {
fn clone_to_box(&self) -> Box<dyn IntoContextElement> {
Box::new(self.clone())
}
}
@ -98,12 +98,18 @@ impl<C: ContextElement> FromContextElement for C {
}
}
pub trait IntoContextElement {
fn into_context_element(&self) -> &dyn ContextElement;
pub trait IntoContextElement: Debug + Walkable + CloneIntoBoxedContextElement {
fn into_context_element(
&self,
breadcrumbs: &Vec<&dyn IntoContextElement>,
) -> &dyn ContextElement;
}
impl<C: ContextElement> IntoContextElement for C {
fn into_context_element(&self) -> &dyn ContextElement {
fn into_context_element(
&self,
breadcrumbs: &Vec<&dyn IntoContextElement>,
) -> &dyn ContextElement {
self
}
}

@ -1,5 +1,6 @@
use crate::renderer::context_element::CompareContextElement;
use crate::renderer::context_element::ContextElement;
use crate::renderer::context_element::IntoContextElement;
use crate::renderer::Loopable;
use crate::renderer::RenderError;
use crate::renderer::Renderable;
@ -61,7 +62,7 @@ impl Loopable for IterationContext {
}
impl Walkable for IterationContext {
fn walk(&self, segment: &str) -> Result<&dyn ContextElement, WalkError> {
fn walk(&self, segment: &str) -> Result<&dyn IntoContextElement, WalkError> {
match segment {
"$idx" => Ok(&self.idx),
"$len" => Ok(&self.len),

@ -26,6 +26,7 @@ use std::{cmp::Ordering, collections::HashMap};
#[derive(Clone, Debug)]
pub enum OwnedRValue {
RVPath(OwnedPath),
RVTemplate(Vec<PartialNameElement>),
RVLiteral(OwnedLiteral),
}
@ -38,9 +39,7 @@ impl From<&RValue<'_>> for OwnedRValue {
fn from(original: &RValue<'_>) -> Self {
match original {
RValue::RVLiteral(literal) => OwnedRValue::RVLiteral(literal.clone()),
RValue::RVTemplate(template) => {
OwnedRValue::RVLiteral(OwnedLiteral::LString("TODO".to_owned()))
}
RValue::RVTemplate(template) => OwnedRValue::RVTemplate(template.clone()),
RValue::RVPath(path) => OwnedRValue::RVPath(OwnedPath {
keys: path.keys.iter().map(|k| k.to_string()).collect(),
}),
@ -51,16 +50,19 @@ impl From<&RValue<'_>> for OwnedRValue {
#[derive(Debug)]
pub struct ParametersContext {
params: HashMap<String, OwnedRValue>,
breadcrumbs: Vec<Box<dyn ContextElement>>,
breadcrumbs: Vec<Box<dyn IntoContextElement>>,
}
impl ParametersContext {
pub fn new(breadcrumbs: &Vec<&dyn ContextElement>, params: &Vec<KVPair>) -> ParametersContext {
pub fn new(
breadcrumbs: &Vec<&dyn IntoContextElement>,
params: &Vec<KVPair>,
) -> ParametersContext {
let owned_params: HashMap<String, OwnedRValue> = params
.iter()
.map(|kvpair| (kvpair.key.to_string(), OwnedRValue::from(&kvpair.value)))
.collect();
let owned_breadcrumbs: Vec<Box<dyn ContextElement>> =
let owned_breadcrumbs: Vec<Box<dyn IntoContextElement>> =
breadcrumbs.iter().map(|ce| ce.clone_to_box()).collect();
ParametersContext {
@ -100,10 +102,11 @@ impl Loopable for ParametersContext {
}
impl Walkable for ParametersContext {
fn walk(&self, segment: &str) -> Result<&dyn ContextElement, WalkError> {
fn walk(&self, segment: &str) -> Result<&dyn IntoContextElement, WalkError> {
let rval = self.params.get(segment).ok_or(WalkError::CantWalk)?;
match rval {
OwnedRValue::RVPath(path) => walk_path(&self.breadcrumbs, &path.keys),
OwnedRValue::RVTemplate(template) => Ok(template),
OwnedRValue::RVLiteral(literal) => Ok(literal),
}
}
@ -120,7 +123,7 @@ impl Clone for ParametersContext {
.iter()
.map(|(k, v)| (k.clone(), v.clone()))
.collect();
let new_breadcrumbs: Vec<Box<dyn ContextElement>> = self
let new_breadcrumbs: Vec<Box<dyn IntoContextElement>> = self
.breadcrumbs
.iter()
.map(|bread| bread.clone_to_box())
@ -171,7 +174,7 @@ impl Loopable for OwnedLiteral {
}
impl Walkable for OwnedLiteral {
fn walk(&self, segment: &str) -> Result<&dyn ContextElement, WalkError> {
fn walk(&self, segment: &str) -> Result<&dyn IntoContextElement, WalkError> {
Err(WalkError::CantWalk)
}
}
@ -238,7 +241,17 @@ impl CompareContextElement for OwnedLiteral {
}
impl IntoContextElement for Vec<PartialNameElement> {
fn into_context_element(&self) -> &dyn ContextElement {
fn into_context_element(
&self,
breadcrumbs: &Vec<&dyn IntoContextElement>,
) -> &dyn ContextElement {
// TODO
&OwnedLiteral::LPositiveInteger(1)
}
}
impl Walkable for Vec<PartialNameElement> {
fn walk(&self, segment: &str) -> Result<&dyn IntoContextElement, WalkError> {
Err(WalkError::CantWalk)
}
}

@ -59,7 +59,7 @@ impl<'a> DustRenderer<'a> {
pub fn render(
&'a self,
name: &str,
breadcrumbs: &Vec<&'a dyn ContextElement>,
breadcrumbs: &Vec<&'a dyn IntoContextElement>,
) -> Result<String, RenderError> {
self.render_template(name, breadcrumbs, None)
}
@ -67,7 +67,7 @@ impl<'a> DustRenderer<'a> {
fn render_template(
&'a self,
name: &str,
breadcrumbs: &Vec<&'a dyn ContextElement>,
breadcrumbs: &Vec<&'a dyn IntoContextElement>,
blocks: Option<&'a InlinePartialTreeElement<'a>>,
) -> Result<String, RenderError> {
let main_template = match self.templates.get(name) {
@ -88,7 +88,7 @@ impl<'a> DustRenderer<'a> {
fn render_maybe_body(
&'a self,
body: &'a Option<Body>,
breadcrumbs: &Vec<&'a dyn ContextElement>,
breadcrumbs: &Vec<&'a dyn IntoContextElement>,
blocks: &'a BlockContext<'a>,
) -> Result<String, RenderError> {
match body {
@ -100,7 +100,7 @@ impl<'a> DustRenderer<'a> {
fn render_body(
&'a self,
body: &'a Body,
breadcrumbs: &Vec<&'a dyn ContextElement>,
breadcrumbs: &Vec<&'a dyn IntoContextElement>,
blocks: &'a BlockContext<'a>,
) -> Result<String, RenderError> {
let mut output = String::new();
@ -120,7 +120,7 @@ impl<'a> DustRenderer<'a> {
fn render_partial_name(
&'a self,
body: &'a Vec<PartialNameElement>,
breadcrumbs: &Vec<&'a dyn ContextElement>,
breadcrumbs: &Vec<&'a dyn IntoContextElement>,
blocks: &'a BlockContext<'a>,
) -> Result<String, RenderError> {
let converted_to_template_elements: Vec<TemplateElement<'a>> =
@ -137,7 +137,7 @@ impl<'a> DustRenderer<'a> {
fn render_tag(
&'a self,
tag: &'a DustTag,
breadcrumbs: &Vec<&'a dyn ContextElement>,
breadcrumbs: &Vec<&'a dyn IntoContextElement>,
blocks: &'a BlockContext<'a>,
) -> Result<String, RenderError> {
match tag {
@ -154,7 +154,8 @@ impl<'a> DustRenderer<'a> {
}
DustTag::DTLiteralStringBlock(literal) => return Ok((*literal).to_owned()),
DustTag::DTReference(reference) => {
let val = walk_path(breadcrumbs, &reference.path.keys);
let val = walk_path(breadcrumbs, &reference.path.keys)
.map(|ice| ice.into_context_element(breadcrumbs));
match val {
Err(WalkError::CantWalk) => return Ok("".to_owned()),
Ok(final_val) => {
@ -168,7 +169,8 @@ impl<'a> DustRenderer<'a> {
}
DustTag::DTSection(container) => {
let injected_context = ParametersContext::new(breadcrumbs, &container.params);
let val = walk_path(breadcrumbs, &container.path.keys);
let val = walk_path(breadcrumbs, &container.path.keys)
.map(|ice| ice.into_context_element(breadcrumbs));
match val {
Err(WalkError::CantWalk) => {
let new_breadcrumbs = Self::new_breadcrumbs_section(
@ -269,7 +271,8 @@ impl<'a> DustRenderer<'a> {
None,
&container.explicit_context,
);
let val = walk_path(breadcrumbs, &container.path.keys);
let val = walk_path(breadcrumbs, &container.path.keys)
.map(|ice| ice.into_context_element(breadcrumbs));
return if val.map(|v| v.is_truthy()).unwrap_or(false) {
self.render_maybe_body(
&container.contents,
@ -291,7 +294,8 @@ impl<'a> DustRenderer<'a> {
None,
&container.explicit_context,
);
let val = walk_path(breadcrumbs, &container.path.keys);
let val = walk_path(breadcrumbs, &container.path.keys)
.map(|ice| ice.into_context_element(breadcrumbs));
return if !val.map(|v| v.is_truthy()).unwrap_or(false) {
self.render_maybe_body(
&container.contents,
@ -391,11 +395,12 @@ impl<'a> DustRenderer<'a> {
let left_side: Result<&dyn ContextElement, WalkError> =
match Self::get_rval(breadcrumbs, &param_map, "key") {
None => return Ok("".to_owned()),
Some(res) => res,
Some(res) => res.map(|ice| ice.into_context_element(breadcrumbs)),
};
let right_side: Result<&dyn ContextElement, WalkError> =
Self::get_rval(breadcrumbs, &param_map, "value")
.unwrap_or(Err(WalkError::CantWalk));
.unwrap_or(Err(WalkError::CantWalk))
.map(|ice| ice.into_context_element(breadcrumbs));
if left_side == right_side {
return self.render_maybe_body(
@ -441,11 +446,12 @@ impl<'a> DustRenderer<'a> {
let left_side: Result<&dyn ContextElement, WalkError> =
match Self::get_rval(breadcrumbs, &param_map, "key") {
None => return Ok("".to_owned()),
Some(res) => res,
Some(res) => res.map(|ice| ice.into_context_element(breadcrumbs)),
};
let right_side: Result<&dyn ContextElement, WalkError> =
Self::get_rval(breadcrumbs, &param_map, "value")
.unwrap_or(Err(WalkError::CantWalk));
.unwrap_or(Err(WalkError::CantWalk))
.map(|ice| ice.into_context_element(breadcrumbs));
if left_side != right_side {
return self.render_maybe_body(
&parameterized_block.contents,
@ -472,11 +478,12 @@ impl<'a> DustRenderer<'a> {
let left_side: Result<&dyn ContextElement, WalkError> =
match Self::get_rval(breadcrumbs, &param_map, "key") {
None => return Ok("".to_owned()),
Some(res) => res,
Some(res) => res.map(|ice| ice.into_context_element(breadcrumbs)),
};
let right_side: Result<&dyn ContextElement, WalkError> =
Self::get_rval(breadcrumbs, &param_map, "value")
.unwrap_or(Err(WalkError::CantWalk));
.unwrap_or(Err(WalkError::CantWalk))
.map(|ice| ice.into_context_element(breadcrumbs));
match (left_side, right_side) {
(Err(_), _) | (_, Err(_)) => {
return self.render_maybe_body(
@ -514,11 +521,12 @@ impl<'a> DustRenderer<'a> {
let left_side: Result<&dyn ContextElement, WalkError> =
match Self::get_rval(breadcrumbs, &param_map, "key") {
None => return Ok("".to_owned()),
Some(res) => res,
Some(res) => res.map(|ice| ice.into_context_element(breadcrumbs)),
};
let right_side: Result<&dyn ContextElement, WalkError> =
Self::get_rval(breadcrumbs, &param_map, "value")
.unwrap_or(Err(WalkError::CantWalk));
.unwrap_or(Err(WalkError::CantWalk))
.map(|ice| ice.into_context_element(breadcrumbs));
match (left_side, right_side) {
(Err(_), _) | (_, Err(_)) => {
return self.render_maybe_body(
@ -556,11 +564,12 @@ impl<'a> DustRenderer<'a> {
let left_side: Result<&dyn ContextElement, WalkError> =
match Self::get_rval(breadcrumbs, &param_map, "key") {
None => return Ok("".to_owned()),
Some(res) => res,
Some(res) => res.map(|ice| ice.into_context_element(breadcrumbs)),
};
let right_side: Result<&dyn ContextElement, WalkError> =
Self::get_rval(breadcrumbs, &param_map, "value")
.unwrap_or(Err(WalkError::CantWalk));
.unwrap_or(Err(WalkError::CantWalk))
.map(|ice| ice.into_context_element(breadcrumbs));
match (left_side, right_side) {
(Err(_), _) | (_, Err(_)) => {
return self.render_maybe_body(
@ -598,11 +607,12 @@ impl<'a> DustRenderer<'a> {
let left_side: Result<&dyn ContextElement, WalkError> =
match Self::get_rval(breadcrumbs, &param_map, "key") {
None => return Ok("".to_owned()),
Some(res) => res,
Some(res) => res.map(|ice| ice.into_context_element(breadcrumbs)),
};
let right_side: Result<&dyn ContextElement, WalkError> =
Self::get_rval(breadcrumbs, &param_map, "value")
.unwrap_or(Err(WalkError::CantWalk));
.unwrap_or(Err(WalkError::CantWalk))
.map(|ice| ice.into_context_element(breadcrumbs));
match (left_side, right_side) {
(Err(_), _) | (_, Err(_)) => {
return self.render_maybe_body(
@ -665,33 +675,17 @@ impl<'a> DustRenderer<'a> {
.collect()
}
fn new_get_rval<'b>(
breadcrumbs: &'b Vec<&'b dyn ContextElement>,
param_map: &HashMap<&str, &'b RValue<'b>>,
key: &str,
) -> Option<Result<&'b dyn IntoContextElement, WalkError>> {
match param_map.get(key) {
None => None,
Some(rval) => match rval {
RValue::RVLiteral(literal) => Some(Ok(literal)),
RValue::RVTemplate(template) => Some(Ok(template)),
RValue::RVPath(path) => {
Some(walk_path(breadcrumbs, &path.keys).map(|ce| ce.from_context_element()))
}
},
}
}
fn get_rval<'b>(
breadcrumbs: &'b Vec<&'b dyn ContextElement>,
breadcrumbs: &'b Vec<&'b dyn IntoContextElement>,
param_map: &HashMap<&str, &'b RValue<'b>>,
key: &str,
) -> Option<Result<&'b dyn ContextElement, WalkError>> {
) -> Option<Result<&'b dyn IntoContextElement, WalkError>> {
match param_map.get(key) {
None => None,
Some(rval) => match rval {
RValue::RVLiteral(literal) => Some(Ok(literal)),
RValue::RVTemplate(template) => None,
// TODO: Do I resolve the IntoContextElement here for RVPath?
RValue::RVPath(path) => Some(walk_path(breadcrumbs, &path.keys)),
},
}
@ -713,12 +707,12 @@ impl<'a> DustRenderer<'a> {
}
fn new_breadcrumbs_section<'b>(
breadcrumbs: &'b Vec<&'b dyn ContextElement>,
index_context: Option<&'b dyn ContextElement>,
injected_context: Option<&'b dyn ContextElement>,
breadcrumbs: &'b Vec<&'b dyn IntoContextElement>,
index_context: Option<&'b dyn IntoContextElement>,
injected_context: Option<&'b dyn IntoContextElement>,
explicit_context: &Option<Path<'b>>,
new_context_element: Option<&'b dyn ContextElement>,
) -> Option<Vec<&'b dyn ContextElement>> {
) -> Option<Vec<&'b dyn IntoContextElement>> {
// If none of the additional contexts are present, return None
// to signal that the original breadcrumbs should be used
// rather than incurring a copy here.
@ -736,24 +730,26 @@ impl<'a> DustRenderer<'a> {
None => breadcrumbs.clone(),
};
explicit_context.as_ref().map(|path| {
walk_path(breadcrumbs, &path.keys).map(|val| {
if val.is_truthy() {
new_stack.push(val)
}
});
walk_path(breadcrumbs, &path.keys)
.map(|ice| ice.into_context_element(breadcrumbs))
.map(|val| {
if val.is_truthy() {
new_stack.push(val.from_context_element())
}
});
});
injected_context.map(|ctx| new_stack.push(ctx));
new_context_element.map(|ctx| new_stack.push(ctx));
new_context_element.map(|ctx| new_stack.push(ctx.from_context_element()));
index_context.map(|ctx| new_stack.push(ctx));
Some(new_stack)
}
fn new_breadcrumbs_partial<'b>(
breadcrumbs: &'b Vec<&'b dyn ContextElement>,
explicit_context_breadcrumbs: &'b Vec<&'b dyn ContextElement>,
injected_context: Option<&'b dyn ContextElement>,
breadcrumbs: &'b Vec<&'b dyn IntoContextElement>,
explicit_context_breadcrumbs: &'b Vec<&'b dyn IntoContextElement>,
injected_context: Option<&'b dyn IntoContextElement>,
explicit_context: &Option<Path<'b>>,
) -> Option<Vec<&'b dyn ContextElement>> {
) -> Option<Vec<&'b dyn IntoContextElement>> {
// If none of the additional contexts are present, return None
// to signal that the original breadcrumbs should be used
// rather than incurring a copy here.
@ -780,18 +776,21 @@ impl<'a> DustRenderer<'a> {
}
});
explicit_context.as_ref().map(|path| {
walk_path(explicit_context_breadcrumbs, &path.keys).map(|val| {
if val.is_truthy() {
new_stack.push(val)
}
});
walk_path(explicit_context_breadcrumbs, &path.keys)
// TODO should resolving the value here use explicit_context_breadcrumbs or breadcrumbs?
.map(|ice| ice.into_context_element(explicit_context_breadcrumbs))
.map(|val| {
if val.is_truthy() {
new_stack.push(val.from_context_element())
}
});
});
Some(new_stack)
}
fn get_index_of_first_non_pseudo_element<'b, B>(breadcrumbs: &'b Vec<B>) -> Option<usize>
where
B: Borrow<dyn ContextElement + 'a>,
B: Borrow<dyn IntoContextElement + 'a>,
{
breadcrumbs
.iter()
@ -801,7 +800,7 @@ impl<'a> DustRenderer<'a> {
struct BlockContext<'a> {
/// The breadcrumbs at the time of entering the current partial
breadcrumbs: &'a Vec<&'a dyn ContextElement>,
breadcrumbs: &'a Vec<&'a dyn IntoContextElement>,
blocks: &'a InlinePartialTreeElement<'a>,
}

@ -1,18 +1,18 @@
use crate::renderer::context_element::ContextElement;
use crate::renderer::context_element::Walkable;
use crate::renderer::context_element::IntoContextElement;
use crate::renderer::WalkError;
use std::borrow::Borrow;
enum WalkResult<'a> {
NoWalk,
PartialWalk,
FullyWalked(&'a dyn ContextElement),
FullyWalked(&'a dyn IntoContextElement),
}
fn walk_path_from_single_level<'a, P, C>(context: &'a C, path: &[P]) -> WalkResult<'a>
where
P: Borrow<str>,
C: Borrow<dyn ContextElement + 'a>,
C: Borrow<dyn IntoContextElement + 'a>,
{
if path.is_empty() {
return WalkResult::FullyWalked(context.borrow());
@ -37,7 +37,7 @@ where
pub fn get_first_non_pseudo_element<'a, B>(breadcrumbs: &'a Vec<B>) -> Option<&B>
where
B: Borrow<dyn ContextElement + 'a>,
B: Borrow<dyn IntoContextElement + 'a>,
{
breadcrumbs
.iter()
@ -49,9 +49,9 @@ where
pub fn walk_path<'a, B, P>(
breadcrumbs: &'a Vec<B>,
path: &Vec<P>,
) -> Result<&'a dyn ContextElement, WalkError>
) -> Result<&'a dyn IntoContextElement, WalkError>
where
B: Borrow<dyn ContextElement + 'a>,
B: Borrow<dyn IntoContextElement + 'a>,
P: Borrow<str>,
{
if breadcrumbs.is_empty() {

Loading…
Cancel
Save