Remove iteration_context, parameters_context, and most of bin.rs.

Since I'm changing a pretty core concept of the renderer, I'm going to be rebuilding it piece by piece. In the interest of being able to rapidly change things and check if they are valid through compilation, I need to eliminate most of the old code so I do not have that weighing me down.
This commit is contained in:
Tom Alexander 2020-05-31 18:27:55 -04:00
parent acb8dfb58e
commit b8b4759d45
Signed by: talexander
GPG Key ID: D3A179C9A53C0EDE
4 changed files with 283 additions and 282 deletions

View File

@ -50,7 +50,7 @@ fn main() {
.first()
.expect("There should be more than 1 template")
.name;
let breadcrumbs = vec![&context as &dyn IntoContextElement];
// let breadcrumbs = vec![&context as &dyn IntoContextElement];
// println!(
// "{}",
// dust_renderer
@ -161,288 +161,288 @@ fn encode_uri_component(inp: &str) -> String {
output
}
fn apply_filter(
json_value: &serde_json::Value,
filter: &Filter,
) -> Result<serde_json::Value, RenderError> {
match (json_value, filter) {
// Html escape filter
(serde_json::Value::String(string), Filter::HtmlEncode) => {
Ok(serde_json::Value::String(html_escape(string)))
}
(_, Filter::HtmlEncode) => Ok(serde_json::Value::String(html_escape(
&json_value.render(&Vec::new())?,
))),
// Disable html escape filter
(_, Filter::DisableHtmlEncode) => panic!("The |s filter is automatically removed by the renderer since it is a no-op during rendering."),
// Parse JSON filter
(serde_json::Value::String(string), Filter::JsonParse) => {
serde_json::from_str(&string).or(Err(RenderError::InvalidJson(string.to_owned())))
}
(_, Filter::JsonParse) => {
let rendered_value = json_value.render(&Vec::new())?;
serde_json::from_str(&rendered_value).or(Err(RenderError::InvalidJson(rendered_value)))
}
// Json Stringify filter
(_, Filter::JsonStringify) => {
Ok(serde_json::Value::String(json_value.to_string()))
}
// Javascript escape filter
(serde_json::Value::String(string), Filter::JavascriptStringEncode) => {
Ok(serde_json::Value::String(javascript_escape(string)))
}
(serde_json::Value::Bool(boolean), Filter::JavascriptStringEncode) => {
Ok(serde_json::Value::Bool(*boolean))
}
(serde_json::Value::Number(number), Filter::JavascriptStringEncode) => {
Ok(serde_json::Value::Number(number.clone()))
}
(serde_json::Value::Array(arr), Filter::JavascriptStringEncode) => {
Ok(serde_json::Value::Array(arr.clone()))
}
(serde_json::Value::Object(obj), Filter::JavascriptStringEncode) => {
Ok(serde_json::Value::Object(obj.clone()))
}
(_, Filter::JavascriptStringEncode) => Ok(serde_json::Value::String(javascript_escape(
&json_value.render(&Vec::new())?,
))),
// EncodeURI filter
(serde_json::Value::String(string), Filter::EncodeUri) => {
Ok(serde_json::Value::String(encode_uri(string)))
}
(_, Filter::EncodeUri) => Ok(serde_json::Value::String(encode_uri(
&json_value.render(&Vec::new())?,
))),
// EncodeURIComponent filter
(serde_json::Value::String(string), Filter::EncodeUriComponent) => {
Ok(serde_json::Value::String(encode_uri_component(string)))
}
(_, Filter::EncodeUriComponent) => Ok(serde_json::Value::String(encode_uri_component(
&json_value.render(&Vec::new())?,
))),
}
}
// fn apply_filter(
// json_value: &serde_json::Value,
// filter: &Filter,
// ) -> Result<serde_json::Value, RenderError> {
// match (json_value, filter) {
// // Html escape filter
// (serde_json::Value::String(string), Filter::HtmlEncode) => {
// Ok(serde_json::Value::String(html_escape(string)))
// }
// (_, Filter::HtmlEncode) => Ok(serde_json::Value::String(html_escape(
// &json_value.render(&Vec::new())?,
// ))),
// // Disable html escape filter
// (_, Filter::DisableHtmlEncode) => panic!("The |s filter is automatically removed by the renderer since it is a no-op during rendering."),
// // Parse JSON filter
// (serde_json::Value::String(string), Filter::JsonParse) => {
// serde_json::from_str(&string).or(Err(RenderError::InvalidJson(string.to_owned())))
// }
// (_, Filter::JsonParse) => {
// let rendered_value = json_value.render(&Vec::new())?;
// serde_json::from_str(&rendered_value).or(Err(RenderError::InvalidJson(rendered_value)))
// }
// // Json Stringify filter
// (_, Filter::JsonStringify) => {
// Ok(serde_json::Value::String(json_value.to_string()))
// }
// // Javascript escape filter
// (serde_json::Value::String(string), Filter::JavascriptStringEncode) => {
// Ok(serde_json::Value::String(javascript_escape(string)))
// }
// (serde_json::Value::Bool(boolean), Filter::JavascriptStringEncode) => {
// Ok(serde_json::Value::Bool(*boolean))
// }
// (serde_json::Value::Number(number), Filter::JavascriptStringEncode) => {
// Ok(serde_json::Value::Number(number.clone()))
// }
// (serde_json::Value::Array(arr), Filter::JavascriptStringEncode) => {
// Ok(serde_json::Value::Array(arr.clone()))
// }
// (serde_json::Value::Object(obj), Filter::JavascriptStringEncode) => {
// Ok(serde_json::Value::Object(obj.clone()))
// }
// (_, Filter::JavascriptStringEncode) => Ok(serde_json::Value::String(javascript_escape(
// &json_value.render(&Vec::new())?,
// ))),
// // EncodeURI filter
// (serde_json::Value::String(string), Filter::EncodeUri) => {
// Ok(serde_json::Value::String(encode_uri(string)))
// }
// (_, Filter::EncodeUri) => Ok(serde_json::Value::String(encode_uri(
// &json_value.render(&Vec::new())?,
// ))),
// // EncodeURIComponent filter
// (serde_json::Value::String(string), Filter::EncodeUriComponent) => {
// Ok(serde_json::Value::String(encode_uri_component(string)))
// }
// (_, Filter::EncodeUriComponent) => Ok(serde_json::Value::String(encode_uri_component(
// &json_value.render(&Vec::new())?,
// ))),
// }
// }
fn apply_filters(
json_value: &serde_json::Value,
filters: &[Filter],
) -> Result<serde_json::Value, RenderError> {
let mut final_value: serde_json::Value = apply_filter(json_value, &filters[0])?;
// fn apply_filters(
// json_value: &serde_json::Value,
// filters: &[Filter],
// ) -> Result<serde_json::Value, RenderError> {
// let mut final_value: serde_json::Value = apply_filter(json_value, &filters[0])?;
for filter in &filters[1..] {
final_value = apply_filter(&final_value, filter)?;
}
// for filter in &filters[1..] {
// final_value = apply_filter(&final_value, filter)?;
// }
Ok(final_value)
}
// Ok(final_value)
// }
impl ContextElement for serde_json::Value {}
// impl ContextElement for serde_json::Value {}
impl Truthiness for serde_json::Value {
fn is_truthy(&self) -> bool {
match self {
serde_json::Value::Null => false,
serde_json::Value::Bool(boolean) => *boolean,
serde_json::Value::Number(_num) => true,
serde_json::Value::String(string_value) => !string_value.is_empty(),
serde_json::Value::Array(array_value) => !array_value.is_empty(),
serde_json::Value::Object(_obj) => true,
}
}
}
// impl Truthiness for serde_json::Value {
// fn is_truthy(&self) -> bool {
// match self {
// serde_json::Value::Null => false,
// serde_json::Value::Bool(boolean) => *boolean,
// serde_json::Value::Number(_num) => true,
// serde_json::Value::String(string_value) => !string_value.is_empty(),
// serde_json::Value::Array(array_value) => !array_value.is_empty(),
// serde_json::Value::Object(_obj) => true,
// }
// }
// }
impl Renderable for serde_json::Value {
fn render(&self, _filters: &Vec<Filter>) -> Result<String, RenderError> {
let after_apply = if _filters.is_empty() {
None
} else {
Some(apply_filters(self, _filters)?)
};
// impl Renderable for serde_json::Value {
// fn render(&self, _filters: &Vec<Filter>) -> Result<String, RenderError> {
// let after_apply = if _filters.is_empty() {
// None
// } else {
// Some(apply_filters(self, _filters)?)
// };
match after_apply.as_ref().unwrap_or(self) {
serde_json::Value::Null => Ok("".to_owned()),
serde_json::Value::Bool(boolean) => Ok(boolean.to_string()),
serde_json::Value::Number(num) => Ok(num.to_string()),
serde_json::Value::String(string) => Ok(string.to_string()),
serde_json::Value::Array(arr) => {
// TODO: Handle the filters instead of passing a Vec::new()
let rendered: Result<Vec<String>, RenderError> =
arr.iter().map(|val| val.render(&Vec::new())).collect();
let rendered_slice: &[String] = &rendered?;
Ok(rendered_slice.join(","))
}
serde_json::Value::Object(_obj) => Ok("[object Object]".to_owned()),
}
}
}
// match after_apply.as_ref().unwrap_or(self) {
// serde_json::Value::Null => Ok("".to_owned()),
// serde_json::Value::Bool(boolean) => Ok(boolean.to_string()),
// serde_json::Value::Number(num) => Ok(num.to_string()),
// serde_json::Value::String(string) => Ok(string.to_string()),
// serde_json::Value::Array(arr) => {
// // TODO: Handle the filters instead of passing a Vec::new()
// let rendered: Result<Vec<String>, RenderError> =
// arr.iter().map(|val| val.render(&Vec::new())).collect();
// let rendered_slice: &[String] = &rendered?;
// Ok(rendered_slice.join(","))
// }
// serde_json::Value::Object(_obj) => Ok("[object Object]".to_owned()),
// }
// }
// }
impl Walkable for serde_json::Value {
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),
serde_json::Value::Number(_num) => Err(WalkError::CantWalk),
serde_json::Value::String(_string) => Err(WalkError::CantWalk),
serde_json::Value::Array(_arr) => Err(WalkError::CantWalk),
serde_json::Value::Object(obj) => obj
.get(segment)
.map(|val| val as _)
.ok_or(WalkError::CantWalk),
}
}
}
// impl Walkable for serde_json::Value {
// 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),
// serde_json::Value::Number(_num) => Err(WalkError::CantWalk),
// serde_json::Value::String(_string) => Err(WalkError::CantWalk),
// serde_json::Value::Array(_arr) => Err(WalkError::CantWalk),
// serde_json::Value::Object(obj) => obj
// .get(segment)
// .map(|val| val as _)
// .ok_or(WalkError::CantWalk),
// }
// }
// }
impl Loopable for serde_json::Value {
fn get_loop_elements(&self) -> Vec<&dyn ContextElement> {
match self {
serde_json::Value::Array(array_value) => array_value.iter().map(|x| x as _).collect(),
_ => Vec::new(),
}
}
}
// impl Loopable for serde_json::Value {
// fn get_loop_elements(&self) -> Vec<&dyn ContextElement> {
// match self {
// serde_json::Value::Array(array_value) => array_value.iter().map(|x| x as _).collect(),
// _ => Vec::new(),
// }
// }
// }
impl CompareContextElement for serde_json::Value {
fn equals(&self, other: &dyn ContextElement) -> bool {
// println!("equals json {:?} | {:?}", self, other);
// Handle other serde_json::Value
match other.to_any().downcast_ref::<Self>() {
None => (),
Some(other_json_value) => match (self, other_json_value) {
// Non-scalar values not caught in the renderer by the
// identical-path shortcut are always not equal.
(serde_json::Value::Array(_), _)
| (_, serde_json::Value::Array(_))
| (serde_json::Value::Object(_), _)
| (_, serde_json::Value::Object(_)) => return false,
_ => return self == other_json_value,
},
}
// Handle literals
match other.to_any().downcast_ref::<OwnedLiteral>() {
None => (),
Some(OwnedLiteral::LString(other_string)) => {
return self.as_str().map_or(false, |s| s == other_string)
}
Some(OwnedLiteral::LPositiveInteger(other_num)) => {
return self.as_u64().map_or(false, |n| n == *other_num)
}
}
false
}
// impl CompareContextElement for serde_json::Value {
// fn equals(&self, other: &dyn ContextElement) -> bool {
// // println!("equals json {:?} | {:?}", self, other);
// // Handle other serde_json::Value
// match other.to_any().downcast_ref::<Self>() {
// None => (),
// Some(other_json_value) => match (self, other_json_value) {
// // Non-scalar values not caught in the renderer by the
// // identical-path shortcut are always not equal.
// (serde_json::Value::Array(_), _)
// | (_, serde_json::Value::Array(_))
// | (serde_json::Value::Object(_), _)
// | (_, serde_json::Value::Object(_)) => return false,
// _ => return self == other_json_value,
// },
// }
// // Handle literals
// match other.to_any().downcast_ref::<OwnedLiteral>() {
// None => (),
// Some(OwnedLiteral::LString(other_string)) => {
// return self.as_str().map_or(false, |s| s == other_string)
// }
// Some(OwnedLiteral::LPositiveInteger(other_num)) => {
// return self.as_u64().map_or(false, |n| n == *other_num)
// }
// }
// false
// }
fn partial_compare(&self, other: &dyn ContextElement) -> Option<Ordering> {
// println!("partial_compare json {:?} | {:?}", self, other);
// Handle type coerced objects
// fn partial_compare(&self, other: &dyn ContextElement) -> Option<Ordering> {
// // println!("partial_compare json {:?} | {:?}", self, other);
// // Handle type coerced objects
// When doing a greater than or less than comparison,
// javascript coerces objects into "[object Object]".
if let serde_json::Value::Object(_) = self {
return OwnedLiteral::LString(self.render(&Vec::new()).unwrap_or("".to_owned()))
.partial_compare(other);
}
// // When doing a greater than or less than comparison,
// // javascript coerces objects into "[object Object]".
// if let serde_json::Value::Object(_) = self {
// return OwnedLiteral::LString(self.render(&Vec::new()).unwrap_or("".to_owned()))
// .partial_compare(other);
// }
// When doing a greater than or less than comparison
// javascript turns arrays into strings.
if let serde_json::Value::Array(_) = self {
return OwnedLiteral::LString(self.render(&Vec::new()).unwrap_or("".to_owned()))
.partial_compare(other);
}
// // When doing a greater than or less than comparison
// // javascript turns arrays into strings.
// if let serde_json::Value::Array(_) = self {
// return OwnedLiteral::LString(self.render(&Vec::new()).unwrap_or("".to_owned()))
// .partial_compare(other);
// }
// Handle other serde_json::Value
match other.to_any().downcast_ref::<Self>() {
None => (),
Some(other_json_value) => {
return match (self, other_json_value) {
(
serde_json::Value::Bool(self_boolean),
serde_json::Value::Bool(other_boolean),
) => self_boolean.partial_cmp(other_boolean),
(
serde_json::Value::Number(self_number),
serde_json::Value::Number(other_number),
) => return compare_json_numbers(self_number, other_number),
(
serde_json::Value::String(self_string),
serde_json::Value::Number(other_number),
) => return compare_json_numbers(self_string, other_number),
(
serde_json::Value::Number(self_number),
serde_json::Value::String(other_string),
) => return compare_json_numbers(self_number, other_string),
(
serde_json::Value::String(self_string),
serde_json::Value::String(other_string),
) => self_string.partial_cmp(other_string),
(
serde_json::Value::Array(self_array),
serde_json::Value::Array(other_array),
) => {
return self
.render(&Vec::new())
.unwrap_or("".to_owned())
.partial_cmp(
&other_json_value
.render(&Vec::new())
.unwrap_or("".to_owned()),
)
}
_ => None,
};
}
}
// Handle literals
match other.to_any().downcast_ref::<OwnedLiteral>() {
None => (),
Some(other_literal) => match (self, other_literal) {
(serde_json::Value::String(self_string), OwnedLiteral::LString(other_string)) => {
return self_string.partial_cmp(other_string)
}
(
serde_json::Value::String(self_string),
OwnedLiteral::LPositiveInteger(other_num),
) => return compare_json_numbers(self_string, other_literal),
(serde_json::Value::Number(self_num), OwnedLiteral::LString(other_string)) => {
return compare_json_numbers(self_num, other_string)
}
(
serde_json::Value::Number(self_num),
OwnedLiteral::LPositiveInteger(other_num),
) => return compare_json_numbers(self_num, other_literal),
(serde_json::Value::Array(_), _) => {
// TODO
todo!()
}
(serde_json::Value::Object(_), _) => {
// TODO
todo!()
}
(serde_json::Value::Bool(_), _) => {
// TODO
todo!()
}
(serde_json::Value::Null, _) => {
// TODO
todo!()
}
},
}
None
}
}
// // Handle other serde_json::Value
// match other.to_any().downcast_ref::<Self>() {
// None => (),
// Some(other_json_value) => {
// return match (self, other_json_value) {
// (
// serde_json::Value::Bool(self_boolean),
// serde_json::Value::Bool(other_boolean),
// ) => self_boolean.partial_cmp(other_boolean),
// (
// serde_json::Value::Number(self_number),
// serde_json::Value::Number(other_number),
// ) => return compare_json_numbers(self_number, other_number),
// (
// serde_json::Value::String(self_string),
// serde_json::Value::Number(other_number),
// ) => return compare_json_numbers(self_string, other_number),
// (
// serde_json::Value::Number(self_number),
// serde_json::Value::String(other_string),
// ) => return compare_json_numbers(self_number, other_string),
// (
// serde_json::Value::String(self_string),
// serde_json::Value::String(other_string),
// ) => self_string.partial_cmp(other_string),
// (
// serde_json::Value::Array(self_array),
// serde_json::Value::Array(other_array),
// ) => {
// return self
// .render(&Vec::new())
// .unwrap_or("".to_owned())
// .partial_cmp(
// &other_json_value
// .render(&Vec::new())
// .unwrap_or("".to_owned()),
// )
// }
// _ => None,
// };
// }
// }
// // Handle literals
// match other.to_any().downcast_ref::<OwnedLiteral>() {
// None => (),
// Some(other_literal) => match (self, other_literal) {
// (serde_json::Value::String(self_string), OwnedLiteral::LString(other_string)) => {
// return self_string.partial_cmp(other_string)
// }
// (
// serde_json::Value::String(self_string),
// OwnedLiteral::LPositiveInteger(other_num),
// ) => return compare_json_numbers(self_string, other_literal),
// (serde_json::Value::Number(self_num), OwnedLiteral::LString(other_string)) => {
// return compare_json_numbers(self_num, other_string)
// }
// (
// serde_json::Value::Number(self_num),
// OwnedLiteral::LPositiveInteger(other_num),
// ) => return compare_json_numbers(self_num, other_literal),
// (serde_json::Value::Array(_), _) => {
// // TODO
// todo!()
// }
// (serde_json::Value::Object(_), _) => {
// // TODO
// todo!()
// }
// (serde_json::Value::Bool(_), _) => {
// // TODO
// todo!()
// }
// (serde_json::Value::Null, _) => {
// // TODO
// todo!()
// }
// },
// }
// None
// }
// }
/// Create a new vec by of references to the serde_json::Values as
/// ContextElement trait objects so we can use its implementation of
/// PartialOrd.
///
/// You cannot implement a trait you do not define for a type you do
/// not define, so I cannot implement PartialOrd for
/// serde_json::value. Instead, I just re-use the PartialOrd
/// implementation for ContextElement which unfortunately has extra
/// overhead of downcasting. This would be a good spot for
/// optimization.
fn convert_vec_to_context_element(array: &Vec<serde_json::Value>) -> Vec<&dyn ContextElement> {
array.iter().map(|v| v as _).collect()
}
// /// Create a new vec by of references to the serde_json::Values as
// /// ContextElement trait objects so we can use its implementation of
// /// PartialOrd.
// ///
// /// You cannot implement a trait you do not define for a type you do
// /// not define, so I cannot implement PartialOrd for
// /// serde_json::value. Instead, I just re-use the PartialOrd
// /// implementation for ContextElement which unfortunately has extra
// /// overhead of downcasting. This would be a good spot for
// /// optimization.
// fn convert_vec_to_context_element(array: &Vec<serde_json::Value>) -> Vec<&dyn ContextElement> {
// array.iter().map(|v| v as _).collect()
// }
#[derive(Debug)]
enum JsonNumber {

View File

@ -1,4 +1,5 @@
use crate::parser::Filter;
use crate::renderer::breadcrumb_tree::BreadcrumbTree;
use crate::renderer::errors::RenderError;
use crate::renderer::errors::WalkError;
use crate::renderer::DustRenderer;
@ -103,7 +104,7 @@ pub trait IntoContextElement: Debug + Walkable + CloneIntoBoxedContextElement {
fn into_context_element(
&self,
renderer: &DustRenderer,
breadcrumbs: &Vec<&dyn IntoContextElement>,
breadcrumbs: Option<&BreadcrumbTree>,
) -> &dyn ContextElement;
}
@ -111,7 +112,7 @@ impl<C: ContextElement> IntoContextElement for C {
fn into_context_element(
&self,
renderer: &DustRenderer,
breadcrumbs: &Vec<&dyn IntoContextElement>,
breadcrumbs: Option<&BreadcrumbTree>,
) -> &dyn ContextElement {
self
}

View File

@ -4,8 +4,8 @@ mod breadcrumb_tree;
mod context_element;
mod errors;
mod inline_partial_tree;
mod iteration_context;
mod parameters_context;
// mod iteration_context;
// mod parameters_context;
mod renderer;
mod tree_walking;
mod walking;

View File

@ -80,17 +80,17 @@ impl<'a> DustRenderer<'a> {
Some(_) => None,
None => maybe_breadcrumbs,
};
let mut new_nodes = Vec::new();
let mut new_nodes: Vec<BreadcrumbTreeElement> = Vec::new();
// explicit_context.as_ref().map(|path| {
// let x = walk_path(maybe_breadcrumbs, &path.keys);
// x.map(|ice| ice.into_context_element(self, breadcrumbs))
// .map(|val| {
// if val.is_truthy() {
// new_nodes.push(val.from_context_element())
// }
// });
// });
explicit_context.as_ref().map(|path| {
let x = walk_path(maybe_breadcrumbs, &path.keys);
x.map(|ice| ice.into_context_element(self, maybe_breadcrumbs))
.map(|val| {
if val.is_truthy() {
new_nodes.push(BreadcrumbTreeElement::Borrowed(val.from_context_element()))
}
});
});
injected_context.map(|ctx| new_nodes.push(BreadcrumbTreeElement::Borrowed(ctx)));
new_context_element
.map(|ctx| new_nodes.push(BreadcrumbTreeElement::Borrowed(ctx.from_context_element())));