Skip to main content

vortex_array/display/
mod.rs

1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright the Vortex contributors
3
4mod tree;
5
6use std::fmt::Display;
7
8use itertools::Itertools as _;
9use tree::TreeDisplayWrapper;
10
11use crate::Array;
12
13/// Describe how to convert an array to a string.
14///
15/// See also:
16/// [Array::display_as](../trait.Array.html#method.display_as)
17/// and [DisplayArrayAs].
18pub enum DisplayOptions {
19    /// Only the top-level encoding id and limited metadata: `vortex.primitive(i16, len=5)`.
20    ///
21    /// ```
22    /// # use vortex_array::display::DisplayOptions;
23    /// # use vortex_array::IntoArray;
24    /// # use vortex_buffer::buffer;
25    /// let array = buffer![0_i16, 1, 2, 3, 4].into_array();
26    /// assert_eq!(
27    ///     format!("{}", array.display_as(DisplayOptions::MetadataOnly)),
28    ///     "vortex.primitive(i16, len=5)",
29    /// );
30    /// ```
31    MetadataOnly,
32    /// Only the logical values of the array: `[0i16, 1i16, 2i16, 3i16, 4i16]`.
33    ///
34    /// ```
35    /// # use vortex_array::display::DisplayOptions;
36    /// # use vortex_array::IntoArray;
37    /// # use vortex_buffer::buffer;
38    /// let array = buffer![0_i16, 1, 2, 3, 4].into_array();
39    /// assert_eq!(
40    ///     format!("{}", array.display_as(DisplayOptions::default())),
41    ///     "[0i16, 1i16, 2i16, 3i16, 4i16]",
42    /// );
43    /// assert_eq!(
44    ///     format!("{}", array.display_as(DisplayOptions::default())),
45    ///     format!("{}", array.display_values()),
46    /// );
47    /// ```
48    CommaSeparatedScalars { omit_comma_after_space: bool },
49    /// The tree of encodings without any concrete values.
50    ///
51    /// With buffers, metadata, and stats:
52    ///
53    /// ```
54    /// # use vortex_array::display::DisplayOptions;
55    /// # use vortex_array::IntoArray;
56    /// # use vortex_buffer::buffer;
57    /// let array = buffer![0_i16, 1, 2, 3, 4].into_array();
58    /// let expected = "root: vortex.primitive(i16, len=5) nbytes=10 B (100.00%)
59    ///   metadata: EmptyMetadata
60    ///   buffer: values host 10 B (align=2) (100.00%)
61    /// ";
62    /// assert_eq!(format!("{}", array.display_as(DisplayOptions::TreeDisplay { buffers: true, metadata: true, stats: true })), expected);
63    ///
64    /// # use vortex_array::arrays::StructArray;
65    /// let array = StructArray::from_fields(&[
66    ///     ("x", buffer![1, 2].into_array()),
67    ///     ("y", buffer![3, 4].into_array()),
68    /// ]).unwrap().into_array();
69    /// let expected = "root: vortex.struct({x=i32, y=i32}, len=2) nbytes=16 B (100.00%)
70    ///   metadata: EmptyMetadata
71    ///   x: vortex.primitive(i32, len=2) nbytes=8 B (50.00%)
72    ///     metadata: EmptyMetadata
73    ///     buffer: values host 8 B (align=4) (100.00%)
74    ///   y: vortex.primitive(i32, len=2) nbytes=8 B (50.00%)
75    ///     metadata: EmptyMetadata
76    ///     buffer: values host 8 B (align=4) (100.00%)
77    /// ";
78    /// assert_eq!(format!("{}", array.display_as(DisplayOptions::TreeDisplay { buffers: true, metadata: true, stats: true })), expected);
79    /// ```
80    ///
81    /// With metadata and stats but no buffers:
82    ///
83    /// ```
84    /// # use vortex_array::display::DisplayOptions;
85    /// # use vortex_array::IntoArray;
86    /// # use vortex_buffer::buffer;
87    /// let array = buffer![0_i16, 1, 2, 3, 4].into_array();
88    /// let expected = "root: vortex.primitive(i16, len=5) nbytes=10 B (100.00%)
89    ///   metadata: EmptyMetadata
90    /// ";
91    /// assert_eq!(format!("{}", array.display_as(DisplayOptions::TreeDisplay { buffers: false, metadata: true, stats: true })), expected);
92    ///
93    /// # use vortex_array::arrays::StructArray;
94    /// let array = StructArray::from_fields(&[
95    ///     ("x", buffer![1, 2].into_array()),
96    ///     ("y", buffer![3, 4].into_array()),
97    /// ]).unwrap().into_array();
98    /// let expected = "root: vortex.struct({x=i32, y=i32}, len=2) nbytes=16 B (100.00%)
99    ///   metadata: EmptyMetadata
100    ///   x: vortex.primitive(i32, len=2) nbytes=8 B (50.00%)
101    ///     metadata: EmptyMetadata
102    ///   y: vortex.primitive(i32, len=2) nbytes=8 B (50.00%)
103    ///     metadata: EmptyMetadata
104    /// ";
105    /// assert_eq!(format!("{}", array.display_as(DisplayOptions::TreeDisplay { buffers: false, metadata: true, stats: true })), expected);
106    /// ```
107    ///
108    /// With metadata and buffers but no stats:
109    ///
110    /// ```
111    /// # use vortex_array::display::DisplayOptions;
112    /// # use vortex_array::IntoArray;
113    /// # use vortex_buffer::buffer;
114    /// let array = buffer![0_i16, 1, 2, 3, 4].into_array();
115    /// let expected = "root: vortex.primitive(i16, len=5)
116    ///   metadata: EmptyMetadata
117    ///   buffer: values host 10 B (align=2)
118    /// ";
119    /// assert_eq!(format!("{}", array.display_as(DisplayOptions::TreeDisplay { buffers: true, metadata: true, stats: false })), expected);
120    ///
121    /// # use vortex_array::arrays::StructArray;
122    /// let array = StructArray::from_fields(&[
123    ///     ("x", buffer![1, 2].into_array()),
124    ///     ("y", buffer![3, 4].into_array()),
125    /// ]).unwrap().into_array();
126    /// let expected = "root: vortex.struct({x=i32, y=i32}, len=2)
127    ///   metadata: EmptyMetadata
128    ///   x: vortex.primitive(i32, len=2)
129    ///     metadata: EmptyMetadata
130    ///     buffer: values host 8 B (align=4)
131    ///   y: vortex.primitive(i32, len=2)
132    ///     metadata: EmptyMetadata
133    ///     buffer: values host 8 B (align=4)
134    /// ";
135    /// assert_eq!(format!("{}", array.display_as(DisplayOptions::TreeDisplay { buffers: true, metadata: true, stats: false })), expected);
136    /// ```
137    ///
138    /// With buffers and stats but no metadata:
139    ///
140    /// ```
141    /// # use vortex_array::display::DisplayOptions;
142    /// # use vortex_array::IntoArray;
143    /// # use vortex_buffer::buffer;
144    /// let array = buffer![0_i16, 1, 2, 3, 4].into_array();
145    /// let expected = "root: vortex.primitive(i16, len=5) nbytes=10 B (100.00%)
146    ///   buffer: values host 10 B (align=2) (100.00%)
147    /// ";
148    /// assert_eq!(format!("{}", array.display_as(DisplayOptions::TreeDisplay { buffers: true, metadata: false, stats: true })), expected);
149    ///
150    /// # use vortex_array::arrays::StructArray;
151    /// let array = StructArray::from_fields(&[
152    ///     ("x", buffer![1, 2].into_array()),
153    ///     ("y", buffer![3, 4].into_array()),
154    /// ]).unwrap().into_array();
155    /// let expected = "root: vortex.struct({x=i32, y=i32}, len=2) nbytes=16 B (100.00%)
156    ///   x: vortex.primitive(i32, len=2) nbytes=8 B (50.00%)
157    ///     buffer: values host 8 B (align=4) (100.00%)
158    ///   y: vortex.primitive(i32, len=2) nbytes=8 B (50.00%)
159    ///     buffer: values host 8 B (align=4) (100.00%)
160    /// ";
161    /// assert_eq!(format!("{}", array.display_as(DisplayOptions::TreeDisplay { buffers: true, metadata: false, stats: true })), expected);
162    /// ```
163    ///
164    /// With just buffers:
165    ///
166    /// ```
167    /// # use vortex_array::display::DisplayOptions;
168    /// # use vortex_array::IntoArray;
169    /// # use vortex_buffer::buffer;
170    /// let array = buffer![0_i16, 1, 2, 3, 4].into_array();
171    /// let expected = "root: vortex.primitive(i16, len=5)
172    ///   buffer: values host 10 B (align=2)
173    /// ";
174    /// assert_eq!(format!("{}", array.display_as(DisplayOptions::TreeDisplay { buffers: true, metadata: false, stats: false })), expected);
175    ///
176    /// # use vortex_array::arrays::StructArray;
177    /// let array = StructArray::from_fields(&[
178    ///     ("x", buffer![1, 2].into_array()),
179    ///     ("y", buffer![3, 4].into_array()),
180    /// ]).unwrap().into_array();
181    /// let expected = "root: vortex.struct({x=i32, y=i32}, len=2)
182    ///   x: vortex.primitive(i32, len=2)
183    ///     buffer: values host 8 B (align=4)
184    ///   y: vortex.primitive(i32, len=2)
185    ///     buffer: values host 8 B (align=4)
186    /// ";
187    /// assert_eq!(format!("{}", array.display_as(DisplayOptions::TreeDisplay { buffers: true, metadata: false, stats: false })), expected);
188    /// ```
189    ///
190    /// With just metadata:
191    ///
192    /// ```
193    /// # use vortex_array::display::DisplayOptions;
194    /// # use vortex_array::IntoArray;
195    /// # use vortex_buffer::buffer;
196    /// let array = buffer![0_i16, 1, 2, 3, 4].into_array();
197    /// let expected = "root: vortex.primitive(i16, len=5)
198    ///   metadata: EmptyMetadata
199    /// ";
200    /// assert_eq!(format!("{}", array.display_as(DisplayOptions::TreeDisplay { buffers: false, metadata: true, stats: false })), expected);
201    ///
202    /// # use vortex_array::arrays::StructArray;
203    /// let array = StructArray::from_fields(&[
204    ///     ("x", buffer![1, 2].into_array()),
205    ///     ("y", buffer![3, 4].into_array()),
206    /// ]).unwrap().into_array();
207    /// let expected = "root: vortex.struct({x=i32, y=i32}, len=2)
208    ///   metadata: EmptyMetadata
209    ///   x: vortex.primitive(i32, len=2)
210    ///     metadata: EmptyMetadata
211    ///   y: vortex.primitive(i32, len=2)
212    ///     metadata: EmptyMetadata
213    /// ";
214    /// assert_eq!(format!("{}", array.display_as(DisplayOptions::TreeDisplay { buffers: false, metadata: true, stats: false })), expected);
215    /// ```
216    ///
217    /// With just stats:
218    ///
219    /// ```
220    /// # use vortex_array::display::DisplayOptions;
221    /// # use vortex_array::IntoArray;
222    /// # use vortex_buffer::buffer;
223    /// let array = buffer![0_i16, 1, 2, 3, 4].into_array();
224    /// let expected = "root: vortex.primitive(i16, len=5) nbytes=10 B (100.00%)
225    /// ";
226    /// assert_eq!(format!("{}", array.display_as(DisplayOptions::TreeDisplay { buffers: false, metadata: false, stats: true })), expected);
227    ///
228    /// # use vortex_array::arrays::StructArray;
229    /// let array = StructArray::from_fields(&[
230    ///     ("x", buffer![1, 2].into_array()),
231    ///     ("y", buffer![3, 4].into_array()),
232    /// ]).unwrap().into_array();
233    /// let expected = "root: vortex.struct({x=i32, y=i32}, len=2) nbytes=16 B (100.00%)
234    ///   x: vortex.primitive(i32, len=2) nbytes=8 B (50.00%)
235    ///   y: vortex.primitive(i32, len=2) nbytes=8 B (50.00%)
236    /// ";
237    /// assert_eq!(format!("{}", array.display_as(DisplayOptions::TreeDisplay { buffers: false, metadata: false, stats: true })), expected);
238    /// ```
239    ///
240    /// With neither buffers, metadata, stats, nor values:
241    ///
242    /// ```
243    /// # use vortex_array::display::DisplayOptions;
244    /// # use vortex_array::IntoArray;
245    /// # use vortex_buffer::buffer;
246    /// let array = buffer![0_i16, 1, 2, 3, 4].into_array();
247    /// let expected = "root: vortex.primitive(i16, len=5)\n";
248    /// assert_eq!(format!("{}", array.display_as(DisplayOptions::TreeDisplay { buffers: false, metadata: false, stats: false })), expected);
249    ///
250    /// # use vortex_array::arrays::StructArray;
251    /// let array = StructArray::from_fields(&[
252    ///     ("x", buffer![1, 2].into_array()),
253    ///     ("y", buffer![3, 4].into_array()),
254    /// ]).unwrap().into_array();
255    /// let expected = "root: vortex.struct({x=i32, y=i32}, len=2)
256    ///   x: vortex.primitive(i32, len=2)
257    ///   y: vortex.primitive(i32, len=2)
258    /// ";
259    /// assert_eq!(format!("{}", array.display_as(DisplayOptions::TreeDisplay { buffers: false, metadata: false, stats: false })), expected);
260    /// ```
261    TreeDisplay {
262        buffers: bool,
263        metadata: bool,
264        stats: bool,
265    },
266    /// Display values in a formatted table with columns.
267    ///
268    /// For struct arrays, displays a column for each field in the struct.
269    /// For regular arrays, displays a single column with values.
270    ///
271    /// ```
272    /// # use vortex_array::display::DisplayOptions;
273    /// # use vortex_array::arrays::StructArray;
274    /// # use vortex_array::IntoArray;
275    /// # use vortex_buffer::buffer;
276    /// let s = StructArray::from_fields(&[
277    ///     ("x", buffer![1, 2].into_array()),
278    ///     ("y", buffer![3, 4].into_array()),
279    /// ]).unwrap().into_array();
280    /// let expected = "
281    /// ┌──────┬──────┐
282    /// │  x   │  y   │
283    /// ├──────┼──────┤
284    /// │ 1i32 │ 3i32 │
285    /// ├──────┼──────┤
286    /// │ 2i32 │ 4i32 │
287    /// └──────┴──────┘".trim();
288    /// assert_eq!(format!("{}", s.display_as(DisplayOptions::TableDisplay)), expected);
289    /// ```
290    #[cfg(feature = "table-display")]
291    TableDisplay,
292}
293
294impl Default for DisplayOptions {
295    fn default() -> Self {
296        Self::CommaSeparatedScalars {
297            omit_comma_after_space: false,
298        }
299    }
300}
301
302/// A shim used to display an array as specified in the options.
303///
304/// See also:
305/// [Array::display_as](../trait.Array.html#method.display_as)
306/// and [DisplayOptions].
307pub struct DisplayArrayAs<'a>(pub &'a dyn Array, pub DisplayOptions);
308
309impl Display for DisplayArrayAs<'_> {
310    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
311        self.0.fmt_as(f, &self.1)
312    }
313}
314
315/// Display the encoding and limited metadata of this array.
316///
317/// # Examples
318/// ```
319/// # use vortex_array::IntoArray;
320/// # use vortex_buffer::buffer;
321/// let array = buffer![0_i16, 1, 2, 3, 4].into_array();
322/// assert_eq!(
323///     format!("{}", array),
324///     "vortex.primitive(i16, len=5)",
325/// );
326/// ```
327impl Display for dyn Array + '_ {
328    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
329        self.fmt_as(f, &DisplayOptions::MetadataOnly)
330    }
331}
332
333impl dyn Array + '_ {
334    /// Display logical values of the array
335    ///
336    /// For example, an `i16` typed array containing the first five non-negative integers is displayed
337    /// as: `[0i16, 1i16, 2i16, 3i16, 4i16]`.
338    ///
339    /// # Examples
340    ///
341    /// ```
342    /// # use vortex_array::IntoArray;
343    /// # use vortex_buffer::buffer;
344    /// let array = buffer![0_i16, 1, 2, 3, 4].into_array();
345    /// assert_eq!(
346    ///     format!("{}", array.display_values()),
347    ///     "[0i16, 1i16, 2i16, 3i16, 4i16]",
348    /// )
349    /// ```
350    ///
351    /// See also:
352    /// [Array::display_as](..//trait.Array.html#method.display_as),
353    /// [DisplayArrayAs], and [DisplayOptions].
354    pub fn display_values(&self) -> impl Display {
355        DisplayArrayAs(
356            self,
357            DisplayOptions::CommaSeparatedScalars {
358                omit_comma_after_space: false,
359            },
360        )
361    }
362
363    /// Display the array as specified by the options.
364    ///
365    /// See [DisplayOptions] for examples.
366    pub fn display_as(&self, options: DisplayOptions) -> impl Display {
367        DisplayArrayAs(self, options)
368    }
369
370    /// Display the tree of array encodings and lengths without metadata, buffers, or stats.
371    ///
372    /// # Examples
373    /// ```
374    /// # use vortex_array::display::DisplayOptions;
375    /// # use vortex_array::IntoArray;
376    /// # use vortex_buffer::buffer;
377    /// let array = buffer![0_i16, 1, 2, 3, 4].into_array();
378    /// let expected = "root: vortex.primitive(i16, len=5)\n";
379    /// assert_eq!(format!("{}", array.display_tree_encodings_only()), expected);
380    ///
381    /// # use vortex_array::arrays::StructArray;
382    /// let array = StructArray::from_fields(&[
383    ///     ("x", buffer![1, 2].into_array()),
384    ///     ("y", buffer![3, 4].into_array()),
385    /// ]).unwrap().into_array();
386    /// let expected = "root: vortex.struct({x=i32, y=i32}, len=2)
387    ///   x: vortex.primitive(i32, len=2)
388    ///   y: vortex.primitive(i32, len=2)
389    /// ";
390    /// assert_eq!(format!("{}", array.display_tree_encodings_only()), expected);
391    /// ```
392    pub fn display_tree_encodings_only(&self) -> impl Display {
393        DisplayArrayAs(
394            self,
395            DisplayOptions::TreeDisplay {
396                buffers: false,
397                metadata: false,
398                stats: false,
399            },
400        )
401    }
402
403    /// Display the tree of encodings of this array as an indented lists.
404    ///
405    /// While some metadata (such as length, bytes and validity-rate) are included, the logical
406    /// values of the array are not displayed. To view the logical values see
407    /// [Array::display_as](../trait.Array.html#method.display_as)
408    /// and [DisplayOptions].
409    ///
410    /// # Examples
411    /// ```
412    /// # use vortex_array::display::DisplayOptions;
413    /// # use vortex_array::IntoArray;
414    /// # use vortex_buffer::buffer;
415    /// let array = buffer![0_i16, 1, 2, 3, 4].into_array();
416    /// let expected = "root: vortex.primitive(i16, len=5) nbytes=10 B (100.00%)
417    ///   metadata: EmptyMetadata
418    ///   buffer: values host 10 B (align=2) (100.00%)
419    /// ";
420    /// assert_eq!(format!("{}", array.display_tree()), expected);
421    /// ```
422    pub fn display_tree(&self) -> impl Display {
423        DisplayArrayAs(
424            self,
425            DisplayOptions::TreeDisplay {
426                buffers: true,
427                metadata: true,
428                stats: true,
429            },
430        )
431    }
432
433    /// Display the array as a formatted table.
434    ///
435    /// For struct arrays, displays a column for each field in the struct.
436    /// For regular arrays, displays a single column with values.
437    ///
438    /// # Examples
439    /// ```
440    /// # #[cfg(feature = "table-display")]
441    /// # {
442    /// # use vortex_array::arrays::StructArray;
443    /// # use vortex_array::IntoArray;
444    /// # use vortex_buffer::buffer;
445    /// let s = StructArray::from_fields(&[
446    ///     ("x", buffer![1, 2].into_array()),
447    ///     ("y", buffer![3, 4].into_array()),
448    /// ]).unwrap().into_array();
449    /// let expected = "
450    /// ┌──────┬──────┐
451    /// │  x   │  y   │
452    /// ├──────┼──────┤
453    /// │ 1i32 │ 3i32 │
454    /// ├──────┼──────┤
455    /// │ 2i32 │ 4i32 │
456    /// └──────┴──────┘".trim();
457    /// assert_eq!(format!("{}", s.display_table()), expected);
458    /// # }
459    /// ```
460    #[cfg(feature = "table-display")]
461    pub fn display_table(&self) -> impl Display {
462        DisplayArrayAs(self, DisplayOptions::TableDisplay)
463    }
464
465    fn fmt_as(&self, f: &mut std::fmt::Formatter, options: &DisplayOptions) -> std::fmt::Result {
466        match options {
467            DisplayOptions::MetadataOnly => {
468                write!(
469                    f,
470                    "{}({}, len={})",
471                    self.encoding_id(),
472                    self.dtype(),
473                    self.len()
474                )
475            }
476            DisplayOptions::CommaSeparatedScalars {
477                omit_comma_after_space,
478            } => {
479                write!(f, "[")?;
480                let sep = if *omit_comma_after_space { "," } else { ", " };
481                write!(
482                    f,
483                    "{}",
484                    (0..self.len())
485                        .map(|i| self
486                            .scalar_at(i)
487                            .map_or_else(|e| format!("<error: {e}>"), |s| s.to_string()))
488                        .format(sep)
489                )?;
490                write!(f, "]")
491            }
492            DisplayOptions::TreeDisplay {
493                buffers,
494                metadata,
495                stats,
496            } => {
497                write!(
498                    f,
499                    "{}",
500                    TreeDisplayWrapper {
501                        array: self.to_array(),
502                        buffers: *buffers,
503                        metadata: *metadata,
504                        stats: *stats
505                    }
506                )
507            }
508            #[cfg(feature = "table-display")]
509            DisplayOptions::TableDisplay => {
510                use vortex_dtype::DType;
511
512                use crate::canonical::ToCanonical;
513
514                let mut builder = tabled::builder::Builder::default();
515
516                // Special logic for struct arrays.
517                let DType::Struct(sf, _) = self.dtype() else {
518                    // For non-struct arrays, simply display a single column table without header.
519                    for row_idx in 0..self.len() {
520                        let value = self
521                            .scalar_at(row_idx)
522                            .map_or_else(|e| format!("<error: {e}>"), |s| s.to_string());
523                        builder.push_record([value]);
524                    }
525
526                    let mut table = builder.build();
527                    table.with(tabled::settings::Style::modern());
528
529                    return write!(f, "{table}");
530                };
531
532                let struct_ = self.to_struct();
533                builder.push_record(sf.names().iter().map(|name| name.to_string()));
534
535                for row_idx in 0..self.len() {
536                    if !self.is_valid(row_idx).unwrap_or(false) {
537                        let null_row = vec!["null".to_string(); sf.names().len()];
538                        builder.push_record(null_row);
539                    } else {
540                        let mut row = Vec::new();
541                        for field_array in struct_.unmasked_fields().iter() {
542                            let value = field_array
543                                .scalar_at(row_idx)
544                                .map_or_else(|e| format!("<error: {e}>"), |s| s.to_string());
545                            row.push(value);
546                        }
547                        builder.push_record(row);
548                    }
549                }
550
551                let mut table = builder.build();
552                table.with(tabled::settings::Style::modern());
553
554                // Center headers
555                for col_idx in 0..sf.names().len() {
556                    table.modify((0, col_idx), tabled::settings::Alignment::center());
557                }
558
559                for row_idx in 0..self.len() {
560                    if !self.is_valid(row_idx).unwrap_or(false) {
561                        table.modify(
562                            (1 + row_idx, 0),
563                            tabled::settings::Span::column(sf.names().len() as isize),
564                        );
565                        table.modify((1 + row_idx, 0), tabled::settings::Alignment::center());
566                    }
567                }
568
569                write!(f, "{table}")
570            }
571        }
572    }
573}
574
575#[cfg(test)]
576mod test {
577    use vortex_buffer::Buffer;
578    use vortex_buffer::buffer;
579    use vortex_dtype::FieldNames;
580
581    use crate::IntoArray as _;
582    use crate::arrays::BoolArray;
583    use crate::arrays::ListArray;
584    use crate::arrays::StructArray;
585    use crate::validity::Validity;
586
587    #[test]
588    fn test_primitive() {
589        let x = Buffer::<u32>::empty().into_array();
590        assert_eq!(x.display_values().to_string(), "[]");
591
592        let x = buffer![1].into_array();
593        assert_eq!(x.display_values().to_string(), "[1i32]");
594
595        let x = buffer![1, 2, 3, 4].into_array();
596        assert_eq!(x.display_values().to_string(), "[1i32, 2i32, 3i32, 4i32]");
597    }
598
599    #[test]
600    fn test_empty_struct() {
601        let s = StructArray::try_new(
602            FieldNames::empty(),
603            vec![],
604            3,
605            Validity::Array(BoolArray::from_iter([true, false, true]).into_array()),
606        )
607        .unwrap()
608        .into_array();
609        assert_eq!(s.display_values().to_string(), "[{}, null, {}]");
610    }
611
612    #[test]
613    fn test_simple_struct() {
614        let s = StructArray::from_fields(&[
615            ("x", buffer![1, 2, 3, 4].into_array()),
616            ("y", buffer![-1, -2, -3, -4].into_array()),
617        ])
618        .unwrap()
619        .into_array();
620        assert_eq!(
621            s.display_values().to_string(),
622            "[{x: 1i32, y: -1i32}, {x: 2i32, y: -2i32}, {x: 3i32, y: -3i32}, {x: 4i32, y: -4i32}]"
623        );
624    }
625
626    #[test]
627    fn test_list() {
628        let x = ListArray::try_new(
629            buffer![1, 2, 3, 4].into_array(),
630            buffer![0, 0, 1, 1, 2, 4].into_array(),
631            Validity::Array(BoolArray::from_iter([true, true, false, true, true]).into_array()),
632        )
633        .unwrap()
634        .into_array();
635        assert_eq!(
636            x.display_values().to_string(),
637            "[[], [1i32], null, [2i32], [3i32, 4i32]]"
638        );
639    }
640
641    #[test]
642    fn test_table_display_primitive() {
643        use crate::display::DisplayOptions;
644
645        let array = buffer![1, 2, 3, 4].into_array();
646        let table_display = array.display_as(DisplayOptions::TableDisplay);
647        assert_eq!(
648            table_display.to_string(),
649            r"
650┌──────┐
651│ 1i32 │
652├──────┤
653│ 2i32 │
654├──────┤
655│ 3i32 │
656├──────┤
657│ 4i32 │
658└──────┘"
659                .trim()
660        );
661    }
662
663    #[test]
664    fn test_table_display() {
665        use crate::display::DisplayOptions;
666
667        let array = crate::arrays::PrimitiveArray::from_option_iter(vec![
668            Some(-1),
669            Some(-2),
670            Some(-3),
671            None,
672        ])
673        .into_array();
674
675        let struct_ = StructArray::try_from_iter_with_validity(
676            [("x", buffer![1, 2, 3, 4].into_array()), ("y", array)],
677            Validity::Array(BoolArray::from_iter([true, false, true, true]).into_array()),
678        )
679        .unwrap()
680        .into_array();
681
682        let table_display = struct_.display_as(DisplayOptions::TableDisplay);
683        assert_eq!(
684            table_display.to_string(),
685            r"
686┌──────┬───────┐
687│  x   │   y   │
688├──────┼───────┤
689│ 1i32 │ -1i32 │
690├──────┼───────┤
691│     null     │
692├──────┼───────┤
693│ 3i32 │ -3i32 │
694├──────┼───────┤
695│ 4i32 │ null  │
696└──────┴───────┘"
697                .trim()
698        );
699    }
700}