Merge branch 'combined_walk_path' into render

This commit is contained in:
Tom Alexander 2020-05-24 15:21:53 -04:00
commit 381ed43645
Signed by: talexander
GPG Key ID: D3A179C9A53C0EDE
3 changed files with 31 additions and 62 deletions

View File

@ -2,7 +2,7 @@ use crate::parser::KVPair;
use crate::parser::{Filter, OwnedLiteral, RValue}; use crate::parser::{Filter, OwnedLiteral, RValue};
use crate::renderer::context_element::CompareContextElement; use crate::renderer::context_element::CompareContextElement;
use crate::renderer::context_element::ContextElement; use crate::renderer::context_element::ContextElement;
use crate::renderer::walking::owned_walk_path; use crate::renderer::walking::walk_path;
use crate::renderer::Loopable; use crate::renderer::Loopable;
use crate::renderer::RenderError; use crate::renderer::RenderError;
use crate::renderer::Renderable; use crate::renderer::Renderable;
@ -89,7 +89,7 @@ impl Walkable for ParametersContext {
fn walk(&self, segment: &str) -> Result<&dyn ContextElement, WalkError> { fn walk(&self, segment: &str) -> Result<&dyn ContextElement, WalkError> {
let rval = self.params.get(segment).ok_or(WalkError::CantWalk)?; let rval = self.params.get(segment).ok_or(WalkError::CantWalk)?;
match rval { match rval {
OwnedRValue::RVPath(path) => owned_walk_path(&self.breadcrumbs, &path.keys), OwnedRValue::RVPath(path) => walk_path(&self.breadcrumbs, &path.keys),
OwnedRValue::RVLiteral(literal) => Ok(literal), OwnedRValue::RVLiteral(literal) => Ok(literal),
} }
} }

View File

@ -489,7 +489,7 @@ impl<'a> DustRenderer<'a> {
} }
fn get_rval<'b>( fn get_rval<'b>(
breadcrumbs: &Vec<&'b dyn ContextElement>, breadcrumbs: &'b Vec<&'b dyn ContextElement>,
param_map: &HashMap<&str, &'b RValue<'b>>, param_map: &HashMap<&str, &'b RValue<'b>>,
key: &str, key: &str,
) -> Option<Result<&'b dyn ContextElement, WalkError>> { ) -> Option<Result<&'b dyn ContextElement, WalkError>> {

View File

@ -1,5 +1,6 @@
use crate::renderer::context_element::ContextElement; use crate::renderer::context_element::ContextElement;
use crate::renderer::WalkError; use crate::renderer::WalkError;
use std::borrow::Borrow;
enum WalkResult<'a> { enum WalkResult<'a> {
NoWalk, NoWalk,
@ -7,18 +8,19 @@ enum WalkResult<'a> {
FullyWalked(&'a dyn ContextElement), FullyWalked(&'a dyn ContextElement),
} }
fn walk_path_from_single_level<'a>( fn walk_path_from_single_level<'a, P, C>(context: &'a C, path: &[P]) -> WalkResult<'a>
context: &'a dyn ContextElement, where
path: &[&str], P: Borrow<str>,
) -> WalkResult<'a> { C: Borrow<dyn ContextElement + 'a>,
{
if path.is_empty() { if path.is_empty() {
return WalkResult::FullyWalked(context); return WalkResult::FullyWalked(context.borrow());
} }
let mut walk_failure = WalkResult::NoWalk; let mut walk_failure = WalkResult::NoWalk;
let mut output = context; let mut output = context.borrow();
for elem in path.iter() { for elem in path.iter() {
match output.walk(elem) { match output.borrow().walk(elem.borrow()) {
Err(WalkError::CantWalk { .. }) => { Err(WalkError::CantWalk { .. }) => {
return walk_failure; return walk_failure;
} }
@ -32,18 +34,28 @@ fn walk_path_from_single_level<'a>(
WalkResult::FullyWalked(output) WalkResult::FullyWalked(output)
} }
pub fn walk_path<'a>( pub fn walk_path<'a, B, P>(
breadcrumbs: &Vec<&'a dyn ContextElement>, breadcrumbs: &'a Vec<B>,
path: &'a Vec<&str>, path: &Vec<P>,
) -> Result<&'a dyn ContextElement, WalkError> { ) -> Result<&'a dyn ContextElement, WalkError>
where
B: Borrow<dyn ContextElement + 'a>,
P: Borrow<str>,
{
if path.is_empty() { if path.is_empty() {
return Ok(*breadcrumbs return Ok(breadcrumbs
.last() .last()
.expect("Breadcrumbs should never be empty")); .expect("Breadcrumbs should never be empty.")
.borrow());
} }
if *path.first().expect("Already proved path is not empty") == "." { if path
.first()
.expect("Already proved path is not empty")
.borrow()
== "."
{
return match walk_path_from_single_level( return match walk_path_from_single_level(
*breadcrumbs breadcrumbs
.last() .last()
.expect("Breadcrumbs should never be empty"), .expect("Breadcrumbs should never be empty"),
&path[1..], &path[1..],
@ -56,50 +68,7 @@ pub fn walk_path<'a>(
}; };
} }
for context in breadcrumbs.iter().rev() { for context in breadcrumbs.iter().rev() {
match walk_path_from_single_level(*context, path) { match walk_path_from_single_level(context, path) {
// If no walking was done at all, keep looping
WalkResult::NoWalk => {}
// If we partially walked then stop trying to find
// anything
WalkResult::PartialWalk => {
return Err(WalkError::CantWalk);
}
WalkResult::FullyWalked(new_context) => return Ok(new_context),
}
}
Err(WalkError::CantWalk)
}
pub fn owned_walk_path<'a>(
breadcrumbs: &'a Vec<Box<dyn ContextElement>>,
path: &Vec<String>,
) -> Result<&'a dyn ContextElement, WalkError> {
if path.is_empty() {
return Ok(breadcrumbs
.last()
.expect("Breadcrumbs should never be empty")
.as_ref());
}
let path_reference: Vec<&str> = path.iter().map(|p| &p[..]).collect();
if path.first().expect("Already proved path is not empty") == "." {
return match walk_path_from_single_level(
breadcrumbs
.last()
.expect("Breadcrumbs should never be empty")
.as_ref(),
&path_reference[1..],
) {
// If no walking was done at all or we partially walked
// then stop trying to find anything because '.' restricts
// us to the current scope
WalkResult::NoWalk | WalkResult::PartialWalk => Err(WalkError::CantWalk),
WalkResult::FullyWalked(new_context) => Ok(new_context),
};
}
for context in breadcrumbs.iter().rev() {
match walk_path_from_single_level(context.as_ref(), &path_reference) {
// If no walking was done at all, keep looping // If no walking was done at all, keep looping
WalkResult::NoWalk => {} WalkResult::NoWalk => {}
// If we partially walked then stop trying to find // If we partially walked then stop trying to find