From 917da5a0733a96f1ecdd016e7d2105da63d90948 Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Sat, 30 May 2020 17:50:27 -0400 Subject: [PATCH] Put IntoContextElement everywhere. It compiles again. --- js/test_cases/reference_parameters/main.dust | 4 + src/bin.rs | 5 +- src/renderer/context_element.rs | 20 +-- src/renderer/iteration_context.rs | 3 +- src/renderer/parameters_context.rs | 33 +++-- src/renderer/renderer.rs | 123 +++++++++---------- src/renderer/walking.rs | 12 +- 7 files changed, 112 insertions(+), 88 deletions(-) diff --git a/js/test_cases/reference_parameters/main.dust b/js/test_cases/reference_parameters/main.dust index ea47d31..0b553cb 100644 --- a/js/test_cases/reference_parameters/main.dust +++ b/js/test_cases/reference_parameters/main.dust @@ -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} diff --git a/src/bin.rs b/src/bin.rs index 2ca7e1a..cb0373f 100644 --- a/src/bin.rs +++ b/src/bin.rs @@ -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), diff --git a/src/renderer/context_element.rs b/src/renderer/context_element.rs index 11cfeac..743f33d 100644 --- a/src/renderer/context_element.rs +++ b/src/renderer/context_element.rs @@ -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; + fn clone_to_box(&self) -> Box; } -impl CloneIntoBoxedContextElement for C { - fn clone_to_box(&self) -> Box { +impl CloneIntoBoxedContextElement for C { + fn clone_to_box(&self) -> Box { Box::new(self.clone()) } } @@ -98,12 +98,18 @@ impl 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 IntoContextElement for C { - fn into_context_element(&self) -> &dyn ContextElement { + fn into_context_element( + &self, + breadcrumbs: &Vec<&dyn IntoContextElement>, + ) -> &dyn ContextElement { self } } diff --git a/src/renderer/iteration_context.rs b/src/renderer/iteration_context.rs index f6a3998..9830137 100644 --- a/src/renderer/iteration_context.rs +++ b/src/renderer/iteration_context.rs @@ -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), diff --git a/src/renderer/parameters_context.rs b/src/renderer/parameters_context.rs index bb9e123..7aa0bf8 100644 --- a/src/renderer/parameters_context.rs +++ b/src/renderer/parameters_context.rs @@ -26,6 +26,7 @@ use std::{cmp::Ordering, collections::HashMap}; #[derive(Clone, Debug)] pub enum OwnedRValue { RVPath(OwnedPath), + RVTemplate(Vec), 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, - breadcrumbs: Vec>, + breadcrumbs: Vec>, } impl ParametersContext { - pub fn new(breadcrumbs: &Vec<&dyn ContextElement>, params: &Vec) -> ParametersContext { + pub fn new( + breadcrumbs: &Vec<&dyn IntoContextElement>, + params: &Vec, + ) -> ParametersContext { let owned_params: HashMap = params .iter() .map(|kvpair| (kvpair.key.to_string(), OwnedRValue::from(&kvpair.value))) .collect(); - let owned_breadcrumbs: Vec> = + let owned_breadcrumbs: Vec> = 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> = self + let new_breadcrumbs: Vec> = 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 { - 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 { + fn walk(&self, segment: &str) -> Result<&dyn IntoContextElement, WalkError> { + Err(WalkError::CantWalk) + } +} diff --git a/src/renderer/renderer.rs b/src/renderer/renderer.rs index f25e28c..4ff2efa 100644 --- a/src/renderer/renderer.rs +++ b/src/renderer/renderer.rs @@ -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 { 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 { 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, - breadcrumbs: &Vec<&'a dyn ContextElement>, + breadcrumbs: &Vec<&'a dyn IntoContextElement>, blocks: &'a BlockContext<'a>, ) -> Result { 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 { let mut output = String::new(); @@ -120,7 +120,7 @@ impl<'a> DustRenderer<'a> { fn render_partial_name( &'a self, body: &'a Vec, - breadcrumbs: &Vec<&'a dyn ContextElement>, + breadcrumbs: &Vec<&'a dyn IntoContextElement>, blocks: &'a BlockContext<'a>, ) -> Result { let converted_to_template_elements: Vec> = @@ -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 { 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, ¶m_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, ¶m_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, ¶m_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, ¶m_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( ¶meterized_block.contents, @@ -472,11 +478,12 @@ impl<'a> DustRenderer<'a> { let left_side: Result<&dyn ContextElement, WalkError> = match Self::get_rval(breadcrumbs, ¶m_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, ¶m_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, ¶m_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, ¶m_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, ¶m_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, ¶m_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, ¶m_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, ¶m_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>, + fn get_rval<'b>( + breadcrumbs: &'b Vec<&'b dyn IntoContextElement>, param_map: &HashMap<&str, &'b RValue<'b>>, key: &str, ) -> Option> { - 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>, - param_map: &HashMap<&str, &'b RValue<'b>>, - key: &str, - ) -> Option> { 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>, new_context_element: Option<&'b dyn ContextElement>, - ) -> Option> { + ) -> Option> { // 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>, - ) -> Option> { + ) -> Option> { // 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) -> Option where - B: Borrow, + B: Borrow, { 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>, } diff --git a/src/renderer/walking.rs b/src/renderer/walking.rs index c0c2365..d56956c 100644 --- a/src/renderer/walking.rs +++ b/src/renderer/walking.rs @@ -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, - C: Borrow, + C: Borrow, { 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) -> Option<&B> where - B: Borrow, + B: Borrow, { breadcrumbs .iter() @@ -49,9 +49,9 @@ where pub fn walk_path<'a, B, P>( breadcrumbs: &'a Vec, path: &Vec

, -) -> Result<&'a dyn ContextElement, WalkError> +) -> Result<&'a dyn IntoContextElement, WalkError> where - B: Borrow, + B: Borrow, P: Borrow, { if breadcrumbs.is_empty() {