From 2b8894f9c27bb863e7435f0152c35d25ad0b9c00 Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Sun, 31 May 2020 20:41:27 -0400 Subject: [PATCH] Most of new_breadcrumbs_partial, just need to get the return working. --- src/renderer/breadcrumb_tree.rs | 20 +++++++- src/renderer/renderer.rs | 83 ++++++++++++++++++++++++++++++++- 2 files changed, 101 insertions(+), 2 deletions(-) diff --git a/src/renderer/breadcrumb_tree.rs b/src/renderer/breadcrumb_tree.rs index 1871e15..c22079f 100644 --- a/src/renderer/breadcrumb_tree.rs +++ b/src/renderer/breadcrumb_tree.rs @@ -1,13 +1,19 @@ use crate::renderer::context_element::IntoContextElement; use std::borrow::Borrow; +use std::rc::Rc; pub struct BreadcrumbTree<'a> { parent: Option<&'a BreadcrumbTree<'a>>, element: BreadcrumbTreeElement<'a>, } +#[derive(Clone, Debug)] pub enum BreadcrumbTreeElement<'a> { - Owned(Box), + // Using Rc so that when we need to create BreadcrumbTrees with + // the same BreadcrumbTreeElement but a different parent (for + // example, when inserting behind the tail), we don't need to the + // copy the already owned/malloc'd data. + Owned(Rc), Borrowed(&'a dyn IntoContextElement), } @@ -27,6 +33,10 @@ impl<'a> BreadcrumbTree<'a> { self.parent } + pub fn get_element(&self) -> &BreadcrumbTreeElement<'a> { + &self.element + } + pub fn ice_iter(&'a self) -> impl Iterator { self.breadcrumb_iter().map(|b| b.get_ice()) } @@ -34,6 +44,14 @@ impl<'a> BreadcrumbTree<'a> { pub fn breadcrumb_iter(&'a self) -> BreadcrumbTreeIterator<'a> { BreadcrumbTreeIterator(Some(self)) } + + pub fn clone_to_new_parent(&self, parent: Option<&'a BreadcrumbTree>) -> Self { + // TODO: Maybe not needed anymore? + BreadcrumbTree { + parent: parent, + element: self.element.clone(), + } + } } impl<'a> Borrow for BreadcrumbTreeElement<'a> { diff --git a/src/renderer/renderer.rs b/src/renderer/renderer.rs index c8e1d67..3245568 100644 --- a/src/renderer/renderer.rs +++ b/src/renderer/renderer.rs @@ -64,7 +64,7 @@ impl<'a> DustRenderer<'a> { // If there is an explicit context, then drop all the current // context - let mut parent = match explicit_context { + let parent = match explicit_context { Some(_) => None, None => maybe_breadcrumbs, }; @@ -86,4 +86,85 @@ impl<'a> DustRenderer<'a> { Some((parent, new_nodes)) } + + fn new_breadcrumbs_partial<'b>( + &self, + maybe_breadcrumbs: Option<&'b BreadcrumbTree>, + explicit_context_maybe_breadcrumbs: Option<&'b BreadcrumbTree>, + injected_context: Option<&'b dyn IntoContextElement>, + explicit_context: &Option>, + ) -> Option<(Option<&'b BreadcrumbTree>, Vec>)> { + // If none of the additional contexts are present, return None + // to signal that the original breadcrumbs should be used + // rather than incurring a copy here. + match (injected_context, explicit_context) { + (None, None) => return None, + _ => (), + }; + + // If there is an explicit context, then drop all the current + // context + let mut parent = match explicit_context { + Some(_) => None, + None => maybe_breadcrumbs, + }; + let mut new_nodes: Vec = Vec::new(); + + injected_context.map(|ctx| { + // Special case: when there is no explicit context, the + // injected context gets inserted 1 spot behind the + // current context. Otherwise, the injected context gets + // added after the current context but before the explicit + // context. + match explicit_context { + None => { + let (new_parent, passed_nodes) = + Self::split_tree_at_predicate(parent, |b| b.get_ice().is_pseudo_element()); + parent = new_parent; + new_nodes.extend(passed_nodes.iter().map(|b| b.get_element().clone())); + } + _ => new_nodes.push(BreadcrumbTreeElement::Borrowed(ctx)), + } + }); + explicit_context.as_ref().map(|path| { + let x = walk_path(maybe_breadcrumbs, &path.keys); + // TODO: should resolving the value here use + // explicit_context_maybe_breadcrumbs or + // maybe_breadcrumbs? + 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())) + } + }); + }); + + None + } + + /// Returns a Breadcrumb tree where all the bottom nodes that do + /// not match the predicate and the first node that match the + /// predicate are shaved off, and a list of those nodes that are + /// shaved off. + fn split_tree_at_predicate<'b, F>( + maybe_breadcrumbs: Option<&'b BreadcrumbTree>, + f: F, + ) -> (Option<&'b BreadcrumbTree<'b>>, Vec<&'b BreadcrumbTree<'b>>) + where + F: Fn(&'b BreadcrumbTree) -> bool, + { + match maybe_breadcrumbs { + None => return (None, Vec::new()), + Some(breadcrumbs) => { + let mut passed_nodes: Vec<&'b BreadcrumbTree<'b>> = Vec::new(); + for tree_node in breadcrumbs { + passed_nodes.push(tree_node); + if f(tree_node) { + return (tree_node.get_parent(), passed_nodes); + } + } + return (None, passed_nodes); + } + } + } }