use crate::parser::Filter; use crate::renderer::breadcrumb_tree::BreadcrumbTree; use crate::renderer::errors::RenderError; use crate::renderer::errors::WalkError; use crate::renderer::DustRenderer; use std::any::Any; use std::{cmp::Ordering, fmt::Debug}; pub trait ContextElement: Debug + Truthiness + Walkable + Renderable + Loopable // + CloneIntoBoxedContextElement + CompareContextElement + FromContextElement { } pub trait Truthiness { fn is_truthy(&self) -> bool; } pub trait Walkable { 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 /// return true. /// /// For example, the iteration context contains $idx and $len but /// it should not be the result of a dot-reference like `{.}`. fn is_pseudo_element(&self) -> bool { false } } pub trait Renderable { fn render(&self, filters: &Vec) -> Result; } pub trait Loopable { /// Return the elements for a Dust section /// /// Sections in dust are accomplished with the {#path} syntax. If /// its an array-like value then it will render n-times, once for /// each element of the array. If this is a scalar value, then /// return an empty array. Sections with scalar values will still /// be rendered (only once) if their truthiness check comes back /// true. fn get_loop_elements(&self) -> Vec<&dyn ContextElement>; } pub trait CastToAny { fn to_any(&self) -> &dyn Any; } pub trait CompareContextElement: CastToAny { fn equals(&self, other: &dyn ContextElement) -> bool; fn partial_compare(&self, other: &dyn ContextElement) -> Option; } // pub trait CloneIntoBoxedContextElement { // fn clone_to_box(&self) -> Box; // } // impl CloneIntoBoxedContextElement for C { // fn clone_to_box(&self) -> Box { // Box::new(self.clone()) // } // } impl CastToAny for C { fn to_any(&self) -> &dyn Any { self } } impl<'a, 'b> PartialEq<&'b dyn ContextElement> for &'a dyn ContextElement { fn eq(&self, other: &&'b dyn ContextElement) -> bool { self.equals(*other) } } impl<'a, 'b> PartialOrd<&'b dyn ContextElement> for &'a dyn ContextElement { fn partial_cmp(&self, other: &&'b dyn ContextElement) -> Option { self.partial_compare(*other) } } pub trait FromContextElement { fn from_context_element(&self) -> &dyn IntoContextElement; } impl FromContextElement for C { fn from_context_element(&self) -> &dyn IntoContextElement { self } } pub trait IntoContextElement: Debug + Walkable /* + CloneIntoBoxedContextElement*/ { fn into_context_element<'a>( &'a self, renderer: &DustRenderer, breadcrumbs: Option<&'a BreadcrumbTree<'a>>, ) -> Option<&'a dyn ContextElement>; } impl IntoContextElement for C { fn into_context_element<'a>( &'a self, renderer: &DustRenderer, breadcrumbs: Option<&'a BreadcrumbTree<'a>>, ) -> Option<&'a dyn ContextElement> { Some(self) } }