Skip to content

Commit c9fcd3a

Browse files
committed
Share tree display traversal and rendering
Signed-off-by: Joe Isaacs <joe.isaacs@live.co.uk>
1 parent 74a2b86 commit c9fcd3a

7 files changed

Lines changed: 388 additions & 89 deletions

File tree

Cargo.lock

Lines changed: 0 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vortex-array/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,6 @@ static_assertions = { workspace = true }
6060
tabled = { workspace = true, optional = true, default-features = false, features = [
6161
"std",
6262
] }
63-
termtree = { workspace = true }
6463
tracing = { workspace = true }
6564
uuid = { workspace = true }
6665
vortex-array-macros = { workspace = true }

vortex-array/src/display/extractor.rs

Lines changed: 13 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@
33

44
use std::fmt;
55

6+
pub use vortex_utils::tree::IndentedFormatter;
7+
use vortex_utils::tree::TreeDisplayContext;
8+
69
use crate::ArrayRef;
10+
use crate::arrays::Chunked;
711

812
/// Context threaded through tree traversal for percentage calculations etc.
913
pub struct TreeContext {
@@ -25,40 +29,19 @@ impl TreeContext {
2529
pub fn parent_total_size(&self) -> Option<u64> {
2630
self.ancestor_sizes.last().cloned().flatten()
2731
}
28-
29-
pub(crate) fn push(&mut self, size: Option<u64>) {
30-
self.ancestor_sizes.push(size);
31-
}
32-
33-
pub(crate) fn pop(&mut self) {
34-
self.ancestor_sizes.pop();
35-
}
3632
}
3733

38-
/// Wrapper providing access to a [`fmt::Formatter`] and the current indentation string.
39-
pub struct IndentedFormatter<'a, 'b> {
40-
inner: &'a mut fmt::Formatter<'b>,
41-
indent: &'a str,
42-
}
43-
44-
impl<'a, 'b> IndentedFormatter<'a, 'b> {
45-
pub(crate) fn new(f: &'a mut fmt::Formatter<'b>, indent: &'a str) -> Self {
46-
Self { inner: f, indent }
47-
}
48-
49-
/// Access the indent string and underlying [`fmt::Formatter`] together.
50-
pub fn parts(&mut self) -> (&str, &mut fmt::Formatter<'b>) {
51-
(self.indent, self.inner)
34+
impl TreeDisplayContext<ArrayRef> for TreeContext {
35+
fn push_parent(&mut self, parent: &ArrayRef) {
36+
self.ancestor_sizes.push(if parent.is::<Chunked>() {
37+
None
38+
} else {
39+
Some(parent.nbytes())
40+
});
5241
}
5342

54-
/// The current indentation string.
55-
pub fn indent(&self) -> &str {
56-
self.indent
57-
}
58-
59-
/// Access the underlying [`fmt::Formatter`].
60-
pub fn formatter(&mut self) -> &mut fmt::Formatter<'b> {
61-
self.inner
43+
fn pop_parent(&mut self, _parent: &ArrayRef) {
44+
self.ancestor_sizes.pop();
6245
}
6346
}
6447

vortex-array/src/display/tree_display.rs

Lines changed: 35 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@
33

44
use std::fmt;
55

6+
use vortex_utils::tree::TreeDisplayAdapter;
7+
use vortex_utils::tree::write_indented_tree;
8+
69
use crate::ArrayRef;
7-
use crate::arrays::Chunked;
810
use crate::display::extractor::IndentedFormatter;
911
use crate::display::extractor::TreeContext;
1012
use crate::display::extractor::TreeExtractor;
@@ -74,54 +76,57 @@ impl TreeDisplay {
7476
self.extractors.push(extractor);
7577
self
7678
}
79+
}
80+
81+
impl TreeDisplayAdapter for TreeDisplay {
82+
type Context = TreeContext;
83+
type Node = ArrayRef;
7784

78-
/// Recursively write a node and all its descendants directly to the formatter.
7985
fn write_node(
8086
&self,
81-
name: &str,
8287
array: &ArrayRef,
83-
ctx: &mut TreeContext,
84-
indent: &str,
88+
ctx: &TreeContext,
8589
f: &mut fmt::Formatter<'_>,
8690
) -> fmt::Result {
87-
// Header line: "{indent}{name}:{annotations...}\n"
88-
write!(f, "{indent}{name}:")?;
8991
for extractor in &self.extractors {
9092
extractor.write_header(array, ctx, f)?;
9193
}
92-
writeln!(f)?;
94+
Ok(())
95+
}
9396

94-
// Detail lines
95-
let child_indent = format!("{indent} ");
96-
{
97-
let mut indented = IndentedFormatter::new(f, &child_indent);
98-
for extractor in &self.extractors {
99-
extractor.write_details(array, ctx, &mut indented)?;
100-
}
97+
fn write_details(
98+
&self,
99+
array: &ArrayRef,
100+
ctx: &TreeContext,
101+
f: &mut IndentedFormatter<'_, '_>,
102+
) -> fmt::Result {
103+
for extractor in &self.extractors {
104+
extractor.write_details(array, ctx, f)?;
101105
}
106+
Ok(())
107+
}
102108

103-
// Push context for children: chunked arrays reset the percentage root
104-
let child_size = if array.is::<Chunked>() {
105-
None
106-
} else {
107-
Some(array.nbytes())
108-
};
109-
ctx.push(child_size);
110-
111-
// Recurse into children
112-
for (child_name, child) in array.children_names().into_iter().zip(array.children()) {
113-
self.write_node(&child_name, &child, ctx, &child_indent, f)?;
109+
fn visit_children(
110+
&self,
111+
array: &ArrayRef,
112+
visit: &mut dyn FnMut(&str, &ArrayRef, bool) -> fmt::Result,
113+
) -> fmt::Result {
114+
let mut children = array
115+
.children_names()
116+
.into_iter()
117+
.zip(array.children())
118+
.peekable();
119+
while let Some((child_name, child)) = children.next() {
120+
let is_last = children.peek().is_none();
121+
visit(&child_name, &child, is_last)?;
114122
}
115-
116-
ctx.pop();
117-
118123
Ok(())
119124
}
120125
}
121126

122127
impl fmt::Display for TreeDisplay {
123128
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
124129
let mut ctx = TreeContext::new();
125-
self.write_node("root", &self.array, &mut ctx, "", f)
130+
write_indented_tree(self, "root", &self.array, &mut ctx, f)
126131
}
127132
}

vortex-array/src/expr/display.rs

Lines changed: 29 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ use std::fmt;
55
use std::fmt::Display;
66
use std::fmt::Formatter;
77

8+
use vortex_utils::tree::TreeDisplayAdapter;
9+
use vortex_utils::tree::write_branch_tree;
10+
811
use crate::expr::BoundExpression;
912
use crate::expr::BoundKind;
1013
use crate::expr::Expression;
@@ -90,39 +93,38 @@ impl DisplayTreeNode for BoundExpression {
9093
}
9194
}
9295

93-
struct NodeDisplay<'a, T>(&'a T);
96+
pub struct DisplayTreeExpr<'a, T: ?Sized = Expression>(pub &'a T);
9497

95-
impl<T: DisplayTreeNode> Display for NodeDisplay<'_, T> {
96-
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
97-
self.0.fmt_tree_node(f)
98+
impl<T: DisplayTreeNode> TreeDisplayAdapter for DisplayTreeExpr<'_, T> {
99+
type Context = ();
100+
type Node = T;
101+
102+
fn write_node(
103+
&self,
104+
node: &Self::Node,
105+
_context: &Self::Context,
106+
formatter: &mut Formatter<'_>,
107+
) -> fmt::Result {
108+
node.fmt_tree_node(formatter)
98109
}
99-
}
100110

101-
pub struct DisplayTreeExpr<'a, T: ?Sized = Expression>(pub &'a T);
111+
fn visit_children(
112+
&self,
113+
node: &Self::Node,
114+
visit: &mut dyn FnMut(&str, &Self::Node, bool) -> fmt::Result,
115+
) -> fmt::Result {
116+
let children = node.tree_children();
117+
for (index, child) in children.iter().enumerate() {
118+
let child_name = node.tree_child_name(index);
119+
visit(child_name.as_ref(), child, index + 1 == children.len())?;
120+
}
121+
Ok(())
122+
}
123+
}
102124

103125
impl<T: DisplayTreeNode> Display for DisplayTreeExpr<'_, T> {
104126
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
105-
pub use termtree::Tree;
106-
fn make_tree<T: DisplayTreeNode>(expr: &T) -> Tree<String> {
107-
let child_trees = expr
108-
.tree_children()
109-
.iter()
110-
.enumerate()
111-
.map(|(index, child)| {
112-
let child_tree = make_tree(child);
113-
Tree::new(format!(
114-
"{}: {}",
115-
expr.tree_child_name(index),
116-
child_tree.root
117-
))
118-
.with_leaves(child_tree.leaves)
119-
})
120-
.collect::<Vec<_>>();
121-
122-
Tree::new(NodeDisplay(expr).to_string()).with_leaves(child_trees)
123-
}
124-
125-
write!(f, "{}", make_tree(self.0))
127+
write_branch_tree(self, self.0, &mut (), f)
126128
}
127129
}
128130

vortex-utils/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@ pub mod debug_with;
1111
pub mod dyn_traits;
1212
pub mod iter;
1313
pub mod parallelism;
14+
pub mod tree;

0 commit comments

Comments
 (0)