port over the equals/not equals helpers.
This commit is contained in:
		
							parent
							
								
									c8de395038
								
							
						
					
					
						commit
						8cbb31251c
					
				| @ -22,7 +22,7 @@ use std::rc::Rc; | ||||
| 
 | ||||
| #[derive(Debug)] | ||||
| pub struct ParametersContext<'a> { | ||||
|     params: HashMap<&'a str, BreadcrumbTreeElement<'a>>, | ||||
|     params: HashMap<&'a str, (&'a RValue<'a>, BreadcrumbTreeElement<'a>)>, | ||||
| } | ||||
| 
 | ||||
| impl<'a> ParametersContext<'a> { | ||||
| @ -39,7 +39,7 @@ impl<'a> ParametersContext<'a> { | ||||
|         // then those are resolved at the time of access rather than
 | ||||
|         // the time of assignment, so we leave them into their
 | ||||
|         // original IntoContextElement state.
 | ||||
|         let rendered_params: HashMap<&'a str, BreadcrumbTreeElement<'a>> = params | ||||
|         let rendered_params: HashMap<&'a str, (&'a RValue<'a>, BreadcrumbTreeElement<'a>)> = params | ||||
|             .iter() | ||||
|             .map(|kvpair| { | ||||
|                 let k = kvpair.key; | ||||
| @ -55,7 +55,7 @@ impl<'a> ParametersContext<'a> { | ||||
|                         Some(BreadcrumbTreeElement::from_borrowed(&kvpair.value)) | ||||
|                     } | ||||
|                 }; | ||||
|                 v.map(|some_v| (k, some_v)) | ||||
|                 v.map(|some_v| (k, (&kvpair.value, some_v))) | ||||
|             }) | ||||
|             // TODO: Should a None value here be the same as a key not existing, or should we store the Nones?
 | ||||
|             .filter_map(|pair| pair) | ||||
| @ -65,6 +65,10 @@ impl<'a> ParametersContext<'a> { | ||||
|             params: rendered_params, | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn get_original_rvalue(&self, segment: &str) -> Option<&'a RValue<'a>> { | ||||
|         self.params.get(segment).map(|(rvalue, _bte)| *rvalue) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl<'a> IntoContextElement for ParametersContext<'a> { | ||||
| @ -81,7 +85,7 @@ impl<'a> Walkable for ParametersContext<'a> { | ||||
|     fn walk(&self, segment: &str) -> Result<&dyn IntoContextElement, WalkError> { | ||||
|         self.params | ||||
|             .get(segment) | ||||
|             .map(|bte| bte.borrow()) | ||||
|             .map(|(_rvalue, bte)| bte.borrow()) | ||||
|             .ok_or(WalkError::CantWalk) | ||||
|     } | ||||
| 
 | ||||
|  | ||||
| @ -2,14 +2,17 @@ use crate::parser::template; | ||||
| use crate::parser::Body; | ||||
| use crate::parser::DustTag; | ||||
| use crate::parser::Filter; | ||||
| use crate::parser::KVPair; | ||||
| use crate::parser::PartialNameElement; | ||||
| use crate::parser::Path; | ||||
| use crate::parser::RValue; | ||||
| use crate::parser::Special; | ||||
| use crate::parser::Template; | ||||
| use crate::parser::TemplateElement; | ||||
| use crate::renderer::breadcrumb_tree::BreadcrumbTreeElement; | ||||
| use crate::renderer::context_element::ContextElement; | ||||
| use crate::renderer::context_element::IntoContextElement; | ||||
| use crate::renderer::context_element::Walkable; | ||||
| use crate::renderer::errors::CompileError; | ||||
| use crate::renderer::errors::RenderError; | ||||
| use crate::renderer::errors::WalkError; | ||||
| @ -362,6 +365,124 @@ impl<'a> DustRenderer<'a> { | ||||
|                     ), | ||||
|                 }; | ||||
|             } | ||||
|             DustTag::DTHelperEquals(parameterized_block) => { | ||||
|                 let new_breadcrumbs = self.new_breadcrumbs_partial( | ||||
|                     breadcrumbs, | ||||
|                     breadcrumbs, | ||||
|                     None, | ||||
|                     ¶meterized_block.explicit_context, | ||||
|                 ); | ||||
| 
 | ||||
|                 let param_map = | ||||
|                     ParametersContext::new(self, breadcrumbs, ¶meterized_block.params); | ||||
| 
 | ||||
|                 // Special case: when comparing two RVPaths, if the
 | ||||
|                 // path is equal then dust assumes the values are
 | ||||
|                 // equal (otherwise, non-scalar values are
 | ||||
|                 // automatically not equal)
 | ||||
|                 if Self::are_paths_identical(¶m_map, "key", "value") { | ||||
|                     return match ¶meterized_block.contents { | ||||
|                         None => Ok("".to_owned()), | ||||
|                         Some(body) => { | ||||
|                             let rendered_content = self.render_body( | ||||
|                                 body, | ||||
|                                 new_breadcrumbs.as_ref().unwrap_or(breadcrumbs), | ||||
|                                 blocks, | ||||
|                             )?; | ||||
|                             Ok(rendered_content) | ||||
|                         } | ||||
|                     }; | ||||
|                 } | ||||
| 
 | ||||
|                 let left_side = match param_map | ||||
|                     .walk("key") | ||||
|                     .map(|ice| ice.into_context_element(self, breadcrumbs)) | ||||
|                 { | ||||
|                     Err(WalkError::CantWalk) | Ok(None) => return Ok("".to_owned()), | ||||
|                     Ok(Some(res)) => res, | ||||
|                 }; | ||||
|                 let right_side = param_map | ||||
|                     .walk("value") | ||||
|                     .map(|ice| ice.into_context_element(self, breadcrumbs)); | ||||
|                 if Ok(Some(left_side.get_context_element_reference())) | ||||
|                     == right_side.as_ref().map(|maybe_ice| { | ||||
|                         maybe_ice | ||||
|                             .as_ref() | ||||
|                             .map(|ice| ice.get_context_element_reference()) | ||||
|                     }) | ||||
|                 { | ||||
|                     return self.render_maybe_body( | ||||
|                         ¶meterized_block.contents, | ||||
|                         new_breadcrumbs.as_ref().unwrap_or(breadcrumbs), | ||||
|                         blocks, | ||||
|                     ); | ||||
|                 } else { | ||||
|                     return self.render_maybe_body( | ||||
|                         ¶meterized_block.else_contents, | ||||
|                         new_breadcrumbs.as_ref().unwrap_or(breadcrumbs), | ||||
|                         blocks, | ||||
|                     ); | ||||
|                 } | ||||
|             } | ||||
|             DustTag::DTHelperNotEquals(parameterized_block) => { | ||||
|                 let new_breadcrumbs = self.new_breadcrumbs_partial( | ||||
|                     breadcrumbs, | ||||
|                     breadcrumbs, | ||||
|                     None, | ||||
|                     ¶meterized_block.explicit_context, | ||||
|                 ); | ||||
| 
 | ||||
|                 let param_map = | ||||
|                     ParametersContext::new(self, breadcrumbs, ¶meterized_block.params); | ||||
| 
 | ||||
|                 // Special case: when comparing two RVPaths, if the
 | ||||
|                 // path is equal then dust assumes the values are
 | ||||
|                 // equal (otherwise, non-scalar values are
 | ||||
|                 // automatically not equal)
 | ||||
|                 if Self::are_paths_identical(¶m_map, "key", "value") { | ||||
|                     return match ¶meterized_block.else_contents { | ||||
|                         None => Ok("".to_owned()), | ||||
|                         Some(body) => { | ||||
|                             let rendered_content = self.render_body( | ||||
|                                 body, | ||||
|                                 new_breadcrumbs.as_ref().unwrap_or(breadcrumbs), | ||||
|                                 blocks, | ||||
|                             )?; | ||||
|                             Ok(rendered_content) | ||||
|                         } | ||||
|                     }; | ||||
|                 } | ||||
| 
 | ||||
|                 let left_side = match param_map | ||||
|                     .walk("key") | ||||
|                     .map(|ice| ice.into_context_element(self, breadcrumbs)) | ||||
|                 { | ||||
|                     Err(WalkError::CantWalk) | Ok(None) => return Ok("".to_owned()), | ||||
|                     Ok(Some(res)) => res, | ||||
|                 }; | ||||
|                 let right_side = param_map | ||||
|                     .walk("value") | ||||
|                     .map(|ice| ice.into_context_element(self, breadcrumbs)); | ||||
|                 if Ok(Some(left_side.get_context_element_reference())) | ||||
|                     != right_side.as_ref().map(|maybe_ice| { | ||||
|                         maybe_ice | ||||
|                             .as_ref() | ||||
|                             .map(|ice| ice.get_context_element_reference()) | ||||
|                     }) | ||||
|                 { | ||||
|                     return self.render_maybe_body( | ||||
|                         ¶meterized_block.contents, | ||||
|                         new_breadcrumbs.as_ref().unwrap_or(breadcrumbs), | ||||
|                         blocks, | ||||
|                     ); | ||||
|                 } else { | ||||
|                     return self.render_maybe_body( | ||||
|                         ¶meterized_block.else_contents, | ||||
|                         new_breadcrumbs.as_ref().unwrap_or(breadcrumbs), | ||||
|                         blocks, | ||||
|                     ); | ||||
|                 } | ||||
|             } | ||||
|             _ => panic!("Unsupported tag"), | ||||
|         } | ||||
|         Ok("".to_owned()) | ||||
| @ -472,6 +593,26 @@ impl<'a> DustRenderer<'a> { | ||||
|         Some(new_stack) | ||||
|     } | ||||
| 
 | ||||
|     fn are_paths_identical<'b>( | ||||
|         param_map: &ParametersContext<'b>, | ||||
|         left_key: &str, | ||||
|         right_key: &str, | ||||
|     ) -> bool { | ||||
|         match ( | ||||
|             param_map.get_original_rvalue(left_key), | ||||
|             param_map.get_original_rvalue(right_key), | ||||
|         ) { | ||||
|             (None, _) => false, | ||||
|             (_, None) => false, | ||||
|             (Some(key_rval), Some(value_rval)) => match (key_rval, value_rval) { | ||||
|                 (RValue::RVPath(key_path), RValue::RVPath(value_path)) => { | ||||
|                     key_path.keys == value_path.keys | ||||
|                 } | ||||
|                 _ => false, | ||||
|             }, | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fn preprocess_filters(filters: &Vec<Filter>) -> Vec<Filter> { | ||||
|         let mut final_filters: Vec<Filter> = filters | ||||
|             .into_iter() | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Tom Alexander
						Tom Alexander