Skip to content

Commit fb4ac44

Browse files
feat[array]: compositional array display logic (#7082)
Breaks up the display logic for array tree into multiple composable extractors --------- Signed-off-by: Joe Isaacs <joe.isaacs@live.co.uk>
1 parent 16f1a7f commit fb4ac44

12 files changed

Lines changed: 742 additions & 324 deletions

File tree

vortex-array/public-api.lock

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10168,12 +10168,126 @@ impl core::default::Default for vortex_array::display::DisplayOptions
1016810168

1016910169
pub fn vortex_array::display::DisplayOptions::default() -> Self
1017010170

10171+
pub struct vortex_array::display::BufferExtractor
10172+
10173+
pub vortex_array::display::BufferExtractor::show_percent: bool
10174+
10175+
impl vortex_array::display::TreeExtractor for vortex_array::display::BufferExtractor
10176+
10177+
pub fn vortex_array::display::BufferExtractor::write_details(&self, array: &dyn vortex_array::DynArray, _ctx: &vortex_array::display::TreeContext, f: &mut vortex_array::display::IndentedFormatter<'_, '_>) -> core::fmt::Result
10178+
10179+
pub fn vortex_array::display::BufferExtractor::write_header(&self, array: &dyn vortex_array::DynArray, ctx: &vortex_array::display::TreeContext, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result
10180+
1017110181
pub struct vortex_array::display::DisplayArrayAs<'a>(pub &'a dyn vortex_array::DynArray, pub vortex_array::display::DisplayOptions)
1017210182

1017310183
impl core::fmt::Display for vortex_array::display::DisplayArrayAs<'_>
1017410184

1017510185
pub fn vortex_array::display::DisplayArrayAs<'_>::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result
1017610186

10187+
pub struct vortex_array::display::EncodingSummaryExtractor
10188+
10189+
impl vortex_array::display::EncodingSummaryExtractor
10190+
10191+
pub fn vortex_array::display::EncodingSummaryExtractor::write(array: &dyn vortex_array::DynArray, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result
10192+
10193+
impl vortex_array::display::TreeExtractor for vortex_array::display::EncodingSummaryExtractor
10194+
10195+
pub fn vortex_array::display::EncodingSummaryExtractor::write_details(&self, array: &dyn vortex_array::DynArray, ctx: &vortex_array::display::TreeContext, f: &mut vortex_array::display::IndentedFormatter<'_, '_>) -> core::fmt::Result
10196+
10197+
pub fn vortex_array::display::EncodingSummaryExtractor::write_header(&self, array: &dyn vortex_array::DynArray, _ctx: &vortex_array::display::TreeContext, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result
10198+
10199+
pub struct vortex_array::display::IndentedFormatter<'a, 'b>
10200+
10201+
impl<'a, 'b> vortex_array::display::IndentedFormatter<'a, 'b>
10202+
10203+
pub fn vortex_array::display::IndentedFormatter<'a, 'b>::formatter(&mut self) -> &mut core::fmt::Formatter<'b>
10204+
10205+
pub fn vortex_array::display::IndentedFormatter<'a, 'b>::indent(&self) -> &str
10206+
10207+
pub fn vortex_array::display::IndentedFormatter<'a, 'b>::parts(&mut self) -> (&str, &mut core::fmt::Formatter<'b>)
10208+
10209+
pub struct vortex_array::display::MetadataExtractor
10210+
10211+
impl vortex_array::display::TreeExtractor for vortex_array::display::MetadataExtractor
10212+
10213+
pub fn vortex_array::display::MetadataExtractor::write_details(&self, array: &dyn vortex_array::DynArray, _ctx: &vortex_array::display::TreeContext, f: &mut vortex_array::display::IndentedFormatter<'_, '_>) -> core::fmt::Result
10214+
10215+
pub fn vortex_array::display::MetadataExtractor::write_header(&self, array: &dyn vortex_array::DynArray, ctx: &vortex_array::display::TreeContext, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result
10216+
10217+
pub struct vortex_array::display::NbytesExtractor
10218+
10219+
impl vortex_array::display::TreeExtractor for vortex_array::display::NbytesExtractor
10220+
10221+
pub fn vortex_array::display::NbytesExtractor::write_details(&self, array: &dyn vortex_array::DynArray, ctx: &vortex_array::display::TreeContext, f: &mut vortex_array::display::IndentedFormatter<'_, '_>) -> core::fmt::Result
10222+
10223+
pub fn vortex_array::display::NbytesExtractor::write_header(&self, array: &dyn vortex_array::DynArray, ctx: &vortex_array::display::TreeContext, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result
10224+
10225+
pub struct vortex_array::display::StatsExtractor
10226+
10227+
impl vortex_array::display::TreeExtractor for vortex_array::display::StatsExtractor
10228+
10229+
pub fn vortex_array::display::StatsExtractor::write_details(&self, array: &dyn vortex_array::DynArray, ctx: &vortex_array::display::TreeContext, f: &mut vortex_array::display::IndentedFormatter<'_, '_>) -> core::fmt::Result
10230+
10231+
pub fn vortex_array::display::StatsExtractor::write_header(&self, array: &dyn vortex_array::DynArray, _ctx: &vortex_array::display::TreeContext, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result
10232+
10233+
pub struct vortex_array::display::TreeContext
10234+
10235+
impl vortex_array::display::TreeContext
10236+
10237+
pub fn vortex_array::display::TreeContext::parent_total_size(&self) -> core::option::Option<u64>
10238+
10239+
pub struct vortex_array::display::TreeDisplay
10240+
10241+
impl vortex_array::display::TreeDisplay
10242+
10243+
pub fn vortex_array::display::TreeDisplay::default_display(array: vortex_array::ArrayRef) -> Self
10244+
10245+
pub fn vortex_array::display::TreeDisplay::new(array: vortex_array::ArrayRef) -> Self
10246+
10247+
pub fn vortex_array::display::TreeDisplay::with<E: vortex_array::display::TreeExtractor + 'static>(self, extractor: E) -> Self
10248+
10249+
pub fn vortex_array::display::TreeDisplay::with_boxed(self, extractor: alloc::boxed::Box<dyn vortex_array::display::TreeExtractor>) -> Self
10250+
10251+
impl core::fmt::Display for vortex_array::display::TreeDisplay
10252+
10253+
pub fn vortex_array::display::TreeDisplay::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result
10254+
10255+
pub trait vortex_array::display::TreeExtractor: core::marker::Send + core::marker::Sync
10256+
10257+
pub fn vortex_array::display::TreeExtractor::write_details(&self, array: &dyn vortex_array::DynArray, ctx: &vortex_array::display::TreeContext, f: &mut vortex_array::display::IndentedFormatter<'_, '_>) -> core::fmt::Result
10258+
10259+
pub fn vortex_array::display::TreeExtractor::write_header(&self, array: &dyn vortex_array::DynArray, ctx: &vortex_array::display::TreeContext, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result
10260+
10261+
impl vortex_array::display::TreeExtractor for vortex_array::display::BufferExtractor
10262+
10263+
pub fn vortex_array::display::BufferExtractor::write_details(&self, array: &dyn vortex_array::DynArray, _ctx: &vortex_array::display::TreeContext, f: &mut vortex_array::display::IndentedFormatter<'_, '_>) -> core::fmt::Result
10264+
10265+
pub fn vortex_array::display::BufferExtractor::write_header(&self, array: &dyn vortex_array::DynArray, ctx: &vortex_array::display::TreeContext, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result
10266+
10267+
impl vortex_array::display::TreeExtractor for vortex_array::display::EncodingSummaryExtractor
10268+
10269+
pub fn vortex_array::display::EncodingSummaryExtractor::write_details(&self, array: &dyn vortex_array::DynArray, ctx: &vortex_array::display::TreeContext, f: &mut vortex_array::display::IndentedFormatter<'_, '_>) -> core::fmt::Result
10270+
10271+
pub fn vortex_array::display::EncodingSummaryExtractor::write_header(&self, array: &dyn vortex_array::DynArray, _ctx: &vortex_array::display::TreeContext, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result
10272+
10273+
impl vortex_array::display::TreeExtractor for vortex_array::display::MetadataExtractor
10274+
10275+
pub fn vortex_array::display::MetadataExtractor::write_details(&self, array: &dyn vortex_array::DynArray, _ctx: &vortex_array::display::TreeContext, f: &mut vortex_array::display::IndentedFormatter<'_, '_>) -> core::fmt::Result
10276+
10277+
pub fn vortex_array::display::MetadataExtractor::write_header(&self, array: &dyn vortex_array::DynArray, ctx: &vortex_array::display::TreeContext, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result
10278+
10279+
impl vortex_array::display::TreeExtractor for vortex_array::display::NbytesExtractor
10280+
10281+
pub fn vortex_array::display::NbytesExtractor::write_details(&self, array: &dyn vortex_array::DynArray, ctx: &vortex_array::display::TreeContext, f: &mut vortex_array::display::IndentedFormatter<'_, '_>) -> core::fmt::Result
10282+
10283+
pub fn vortex_array::display::NbytesExtractor::write_header(&self, array: &dyn vortex_array::DynArray, ctx: &vortex_array::display::TreeContext, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result
10284+
10285+
impl vortex_array::display::TreeExtractor for vortex_array::display::StatsExtractor
10286+
10287+
pub fn vortex_array::display::StatsExtractor::write_details(&self, array: &dyn vortex_array::DynArray, ctx: &vortex_array::display::TreeContext, f: &mut vortex_array::display::IndentedFormatter<'_, '_>) -> core::fmt::Result
10288+
10289+
pub fn vortex_array::display::StatsExtractor::write_header(&self, array: &dyn vortex_array::DynArray, _ctx: &vortex_array::display::TreeContext, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result
10290+
1017710291
pub mod vortex_array::dtype
1017810292

1017910293
pub use vortex_array::dtype::half
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
// SPDX-FileCopyrightText: Copyright the Vortex contributors
3+
4+
use std::fmt;
5+
6+
use crate::DynArray;
7+
8+
/// Context threaded through tree traversal for percentage calculations etc.
9+
pub struct TreeContext {
10+
/// Stack of ancestor nbytes values. `None` entries reset the percentage root
11+
/// (e.g. for chunked arrays where each chunk is its own root).
12+
pub(crate) ancestor_sizes: Vec<Option<u64>>,
13+
}
14+
15+
impl TreeContext {
16+
pub(crate) fn new() -> Self {
17+
Self {
18+
ancestor_sizes: Vec::new(),
19+
}
20+
}
21+
22+
/// The total size used as the denominator for percentage calculations.
23+
/// Returns `None` if there is no ancestor (i.e., this node is the root or
24+
/// a chunk boundary reset the percentage root).
25+
pub fn parent_total_size(&self) -> Option<u64> {
26+
self.ancestor_sizes.last().cloned().flatten()
27+
}
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+
}
36+
}
37+
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)
52+
}
53+
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
62+
}
63+
}
64+
65+
/// Trait for contributing display information to tree nodes.
66+
///
67+
/// Each extractor represents one "dimension" of display (e.g., nbytes, stats, metadata, buffers).
68+
/// Extractors are composable: you can combine any number of them via [`TreeDisplay::with`].
69+
///
70+
/// [`TreeDisplay::with`]: super::TreeDisplay::with
71+
pub trait TreeExtractor: Send + Sync {
72+
/// Write header annotations (space-prefixed) to the formatter.
73+
fn write_header(
74+
&self,
75+
array: &dyn DynArray,
76+
ctx: &TreeContext,
77+
f: &mut fmt::Formatter<'_>,
78+
) -> fmt::Result {
79+
let _ = (array, ctx, f);
80+
Ok(())
81+
}
82+
83+
/// Write detail lines below the header.
84+
///
85+
/// Content written through `f` is automatically indented. Use
86+
/// [`f.formatter()`](IndentedFormatter::formatter) to access the underlying
87+
/// [`fmt::Formatter`] for formatting flags.
88+
fn write_details(
89+
&self,
90+
array: &dyn DynArray,
91+
ctx: &TreeContext,
92+
f: &mut IndentedFormatter<'_, '_>,
93+
) -> fmt::Result {
94+
let _ = (array, ctx, f);
95+
Ok(())
96+
}
97+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
// SPDX-FileCopyrightText: Copyright the Vortex contributors
3+
4+
use std::fmt;
5+
6+
use humansize::DECIMAL;
7+
use humansize::format_size;
8+
9+
use crate::DynArray;
10+
use crate::display::extractor::IndentedFormatter;
11+
use crate::display::extractor::TreeContext;
12+
use crate::display::extractor::TreeExtractor;
13+
14+
/// Extractor that adds buffer detail lines.
15+
pub struct BufferExtractor {
16+
/// Whether to show buffer-level percentage of parent nbytes.
17+
pub show_percent: bool,
18+
}
19+
20+
impl TreeExtractor for BufferExtractor {
21+
fn write_details(
22+
&self,
23+
array: &dyn DynArray,
24+
_ctx: &TreeContext,
25+
f: &mut IndentedFormatter<'_, '_>,
26+
) -> fmt::Result {
27+
let (indent, f) = f.parts();
28+
let nbytes = array.nbytes();
29+
for (name, buffer) in array.named_buffers() {
30+
let loc = if buffer.is_on_device() {
31+
"device"
32+
} else if buffer.is_on_host() {
33+
"host"
34+
} else {
35+
"location-unknown"
36+
};
37+
let align = if buffer.is_on_host() {
38+
buffer.as_host().alignment().to_string()
39+
} else {
40+
String::new()
41+
};
42+
43+
if self.show_percent {
44+
let buffer_percent = if nbytes == 0 {
45+
0.0
46+
} else {
47+
100_f64 * buffer.len() as f64 / nbytes as f64
48+
};
49+
writeln!(
50+
f,
51+
"{indent}buffer: {} {loc} {} (align={}) ({:.2}%)",
52+
name,
53+
format_size(buffer.len(), DECIMAL),
54+
align,
55+
buffer_percent,
56+
)?;
57+
} else {
58+
writeln!(
59+
f,
60+
"{indent}buffer: {} {loc} {} (align={})",
61+
name,
62+
format_size(buffer.len(), DECIMAL),
63+
align,
64+
)?;
65+
}
66+
}
67+
Ok(())
68+
}
69+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
// SPDX-FileCopyrightText: Copyright the Vortex contributors
3+
4+
use std::fmt;
5+
6+
use crate::DynArray;
7+
use crate::display::extractor::TreeContext;
8+
use crate::display::extractor::TreeExtractor;
9+
10+
/// Extractor that adds the encoding summary (e.g. `vortex.primitive(i16, len=5)`) to the header.
11+
pub struct EncodingSummaryExtractor;
12+
13+
impl EncodingSummaryExtractor {
14+
/// Write the encoding summary for an array directly to a formatter.
15+
pub fn write(array: &dyn DynArray, f: &mut fmt::Formatter<'_>) -> fmt::Result {
16+
write!(
17+
f,
18+
"{}({}, len={})",
19+
array.encoding_id(),
20+
array.dtype(),
21+
array.len()
22+
)
23+
}
24+
}
25+
26+
impl TreeExtractor for EncodingSummaryExtractor {
27+
fn write_header(
28+
&self,
29+
array: &dyn DynArray,
30+
_ctx: &TreeContext,
31+
f: &mut fmt::Formatter<'_>,
32+
) -> fmt::Result {
33+
write!(f, " ")?;
34+
Self::write(array, f)
35+
}
36+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
// SPDX-FileCopyrightText: Copyright the Vortex contributors
3+
4+
use std::fmt;
5+
6+
use crate::DynArray;
7+
use crate::display::extractor::IndentedFormatter;
8+
use crate::display::extractor::TreeContext;
9+
use crate::display::extractor::TreeExtractor;
10+
11+
/// Extractor that adds a `metadata: ...` detail line.
12+
pub struct MetadataExtractor;
13+
14+
impl TreeExtractor for MetadataExtractor {
15+
fn write_details(
16+
&self,
17+
array: &dyn DynArray,
18+
_ctx: &TreeContext,
19+
f: &mut IndentedFormatter<'_, '_>,
20+
) -> fmt::Result {
21+
let (indent, f) = f.parts();
22+
write!(f, "{indent}metadata: ")?;
23+
array.metadata_fmt(f)?;
24+
writeln!(f)
25+
}
26+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
// SPDX-FileCopyrightText: Copyright the Vortex contributors
3+
4+
mod buffer;
5+
mod encoding_summary;
6+
mod metadata;
7+
mod nbytes;
8+
mod stats;
9+
10+
pub use buffer::BufferExtractor;
11+
pub use encoding_summary::EncodingSummaryExtractor;
12+
pub use metadata::MetadataExtractor;
13+
pub use nbytes::NbytesExtractor;
14+
pub use stats::StatsExtractor;

0 commit comments

Comments
 (0)