Partial simple is working.

This commit is contained in:
Tom Alexander 2020-05-09 14:53:53 -04:00
parent ad498abb74
commit bbb9b8d9d3
Signed by: talexander
GPG Key ID: D3A179C9A53C0EDE
3 changed files with 37 additions and 53 deletions

View File

@ -4,6 +4,7 @@ mod context_element;
mod errors;
mod parameters_context;
mod renderer;
mod walking;
pub use context_element::ContextElement;
pub use context_element::Loopable;

View File

@ -1,6 +1,7 @@
use crate::parser::KVPair;
use crate::parser::{Filter, RValue};
use crate::renderer::context_element::ContextElement;
use crate::renderer::walking::walk_path;
use crate::renderer::Loopable;
use crate::renderer::RenderError;
use crate::renderer::Renderable;
@ -34,20 +35,52 @@ impl<'a> ContextElement for ParametersContext<'a> {}
impl<'a> Renderable for ParametersContext<'a> {
fn render(&self, _filters: &Vec<Filter>) -> Result<String, RenderError> {
// TODO: Would this even ever be called? Won't matter, but I'd
// like to know. Since it is injected 1 above the current
// context, we wouldn't be able to access it with `{.}`.
Ok("[object Object]".to_owned())
}
}
impl<'a> Loopable for ParametersContext<'a> {
fn get_loop_elements(&self) -> Vec<&dyn ContextElement> {
// TODO: Would this even ever be called? Won't matter, but I'd like to know.
// TODO: Would this even ever be called? Won't matter, but I'd
// like to know. Since it is injected 1 above the current
// context, we wouldn't be able to access it with `{.}`.
vec![self]
}
}
impl<'a> Walkable for ParametersContext<'a> {
fn walk(&self, segment: &str) -> Result<&dyn ContextElement, WalkError> {
// TODO: Actually implement
let rval = self.params.get(segment).ok_or(WalkError::CantWalk)?;
match rval {
RValue::RVPath(path) => walk_path(self.breadcrumbs, &path.keys),
RValue::RVString(text) => Ok(text),
}
}
}
impl ContextElement for String {}
impl Renderable for String {
fn render(&self, _filters: &Vec<Filter>) -> Result<String, RenderError> {
Ok(self.clone())
}
}
impl Loopable for String {
fn get_loop_elements(&self) -> Vec<&dyn ContextElement> {
if self.is_empty() {
Vec::new()
} else {
vec![self]
}
}
}
impl Walkable for String {
fn walk(&self, segment: &str) -> Result<&dyn ContextElement, WalkError> {
Err(WalkError::CantWalk)
}
}

View File

@ -9,6 +9,7 @@ use crate::renderer::errors::CompileError;
use crate::renderer::errors::RenderError;
use crate::renderer::errors::WalkError;
use crate::renderer::parameters_context::ParametersContext;
use crate::renderer::walking::walk_path;
use std::collections::HashMap;
#[derive(Clone, Debug)]
@ -202,57 +203,6 @@ impl<'a> DustRenderer<'a> {
}
}
enum WalkResult<'a> {
NoWalk,
PartialWalk,
FullyWalked(&'a dyn ContextElement),
}
fn walk_path_from_single_level<'a>(
context: &'a dyn ContextElement,
path: &Vec<&str>,
) -> WalkResult<'a> {
if path.is_empty() {
return WalkResult::FullyWalked(context);
}
let mut walk_failure = WalkResult::NoWalk;
let mut output = context;
for elem in path.iter() {
let new_val = output.walk(elem);
match output.walk(elem) {
Err(WalkError::CantWalk { .. }) => {
return walk_failure;
}
Ok(new_val) => {
walk_failure = WalkResult::PartialWalk;
output = new_val;
}
}
}
WalkResult::FullyWalked(output)
}
fn walk_path<'a>(
breadcrumbs: &Vec<&'a dyn ContextElement>,
path: &'a Vec<&str>,
) -> Result<&'a dyn ContextElement, WalkError> {
for context in breadcrumbs.iter().rev() {
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)
}
#[cfg(test)]
mod tests {
use super::*;