11// SPDX-License-Identifier: Apache-2.0
22// SPDX-FileCopyrightText: Copyright the Vortex contributors
33
4+ use std:: fmt:: Write ;
45use std:: fmt:: { self } ;
56
67use humansize:: DECIMAL ;
78use humansize:: format_size;
89
10+ use crate :: Array ;
911use crate :: ArrayRef ;
1012use crate :: ArrayVisitor ;
1113use crate :: arrays:: ChunkedVTable ;
1214use crate :: display:: DisplayOptions ;
15+ use crate :: expr:: stats:: Stat ;
16+ use crate :: expr:: stats:: StatsProvider ;
17+
18+ /// Display wrapper for array statistics in compact format.
19+ struct StatsDisplay < ' a > ( & ' a dyn Array ) ;
20+
21+ impl fmt:: Display for StatsDisplay < ' _ > {
22+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
23+ let stats = self . 0 . statistics ( ) ;
24+ let mut first = true ;
25+
26+ // Helper to write separator
27+ let mut sep = |f : & mut fmt:: Formatter < ' _ > | -> fmt:: Result {
28+ if first {
29+ first = false ;
30+ f. write_str ( " [" )
31+ } else {
32+ f. write_str ( ", " )
33+ }
34+ } ;
35+
36+ // Null count or validity fallback
37+ if let Some ( nc) = stats. get ( Stat :: NullCount ) {
38+ if let Ok ( n) = usize:: try_from ( & nc. clone ( ) . into_inner ( ) ) {
39+ sep ( f) ?;
40+ write ! ( f, "nulls={}" , n) ?;
41+ } else {
42+ sep ( f) ?;
43+ write ! ( f, "nulls={}" , nc) ?;
44+ }
45+ } else if self . 0 . dtype ( ) . is_nullable ( ) {
46+ if self . 0 . all_valid ( ) {
47+ sep ( f) ?;
48+ f. write_str ( "all_valid" ) ?;
49+ } else if self . 0 . all_invalid ( ) {
50+ sep ( f) ?;
51+ f. write_str ( "all_invalid" ) ?;
52+ }
53+ }
54+
55+ // NaN count (only if > 0)
56+ if let Some ( nan) = stats. get ( Stat :: NaNCount ) {
57+ if let Ok ( n) = usize:: try_from ( & nan. clone ( ) . into_inner ( ) ) {
58+ if n > 0 {
59+ sep ( f) ?;
60+ write ! ( f, "nan={}" , n) ?;
61+ }
62+ }
63+ }
64+
65+ // Min/Max
66+ if let Some ( min) = stats. get ( Stat :: Min ) {
67+ sep ( f) ?;
68+ write ! ( f, "min={}" , min) ?;
69+ }
70+ if let Some ( max) = stats. get ( Stat :: Max ) {
71+ sep ( f) ?;
72+ write ! ( f, "max={}" , max) ?;
73+ }
74+
75+ // Sum
76+ if let Some ( sum) = stats. get ( Stat :: Sum ) {
77+ sep ( f) ?;
78+ write ! ( f, "sum={}" , sum) ?;
79+ }
80+
81+ // Boolean flags (compact)
82+ if let Some ( c) = stats. get ( Stat :: IsConstant ) {
83+ if bool:: try_from ( & c. into_inner ( ) ) . unwrap_or ( false ) {
84+ sep ( f) ?;
85+ f. write_str ( "const" ) ?;
86+ }
87+ }
88+ if let Some ( s) = stats. get ( Stat :: IsStrictSorted ) {
89+ if bool:: try_from ( & s. into_inner ( ) ) . unwrap_or ( false ) {
90+ sep ( f) ?;
91+ f. write_str ( "strict" ) ?;
92+ }
93+ } else if let Some ( s) = stats. get ( Stat :: IsSorted ) {
94+ if bool:: try_from ( & s. into_inner ( ) ) . unwrap_or ( false ) {
95+ sep ( f) ?;
96+ f. write_str ( "sorted" ) ?;
97+ }
98+ }
99+
100+ // Close bracket if we wrote anything
101+ if !first {
102+ f. write_char ( ']' ) ?;
103+ }
104+
105+ Ok ( ( ) )
106+ }
107+ }
13108
14109pub ( crate ) struct TreeDisplayWrapper ( pub ( crate ) ArrayRef ) ;
15110
@@ -39,16 +134,6 @@ impl<'a, 'b: 'a> TreeFormatter<'a, 'b> {
39134 } else {
40135 100_f64 * nbytes as f64 / total_size as f64
41136 } ;
42- // Compute validity status string
43- let validity_str = if !array. dtype ( ) . is_nullable ( ) {
44- ""
45- } else if array. all_valid ( ) {
46- " all_valid"
47- } else if array. all_invalid ( ) {
48- " all_invalid"
49- } else {
50- ""
51- } ;
52137
53138 writeln ! (
54139 self ,
@@ -57,7 +142,7 @@ impl<'a, 'b: 'a> TreeFormatter<'a, 'b> {
57142 array. display_as( DisplayOptions :: MetadataOnly ) ,
58143 format_size( nbytes, DECIMAL ) ,
59144 percent,
60- validity_str
145+ StatsDisplay ( array . as_ref ( ) ) ,
61146 ) ?;
62147
63148 self . indent ( |i| {
0 commit comments