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::DynArray;
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 DynArray, 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 DynArray + '_ {
328    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
329        self.fmt_as(f, &DisplayOptions::MetadataOnly)
330    }
331}
332
333const DISPLAY_LIMIT: usize = 16;
334impl dyn DynArray + '_ {
335    /// Display logical values of the array
336    ///
337    /// For example, an `i16` typed array containing the first five non-negative integers is displayed
338    /// as: `[0i16, 1i16, 2i16, 3i16, 4i16]`.
339    ///
340    /// # Examples
341    ///
342    /// ```
343    /// # use vortex_array::IntoArray;
344    /// # use vortex_buffer::buffer;
345    /// let array = buffer![0_i16, 1, 2, 3, 4].into_array();
346    /// assert_eq!(
347    ///     format!("{}", array.display_values()),
348    ///     "[0i16, 1i16, 2i16, 3i16, 4i16]",
349    /// )
350    /// ```
351    ///
352    /// See also:
353    /// [Array::display_as](..//trait.Array.html#method.display_as),
354    /// [DisplayArrayAs], and [DisplayOptions].
355    pub fn display_values(&self) -> impl Display {
356        DisplayArrayAs(
357            self,
358            DisplayOptions::CommaSeparatedScalars {
359                omit_comma_after_space: false,
360            },
361        )
362    }
363
364    /// Display the array as specified by the options.
365    ///
366    /// See [DisplayOptions] for examples.
367    pub fn display_as(&self, options: DisplayOptions) -> impl Display {
368        DisplayArrayAs(self, options)
369    }
370
371    /// Display the tree of array encodings and lengths without metadata, buffers, or stats.
372    ///
373    /// # Examples
374    /// ```
375    /// # use vortex_array::display::DisplayOptions;
376    /// # use vortex_array::IntoArray;
377    /// # use vortex_buffer::buffer;
378    /// let array = buffer![0_i16, 1, 2, 3, 4].into_array();
379    /// let expected = "root: vortex.primitive(i16, len=5)\n";
380    /// assert_eq!(format!("{}", array.display_tree_encodings_only()), expected);
381    ///
382    /// # use vortex_array::arrays::StructArray;
383    /// let array = StructArray::from_fields(&[
384    ///     ("x", buffer![1, 2].into_array()),
385    ///     ("y", buffer![3, 4].into_array()),
386    /// ]).unwrap().into_array();
387    /// let expected = "root: vortex.struct({x=i32, y=i32}, len=2)
388    ///   x: vortex.primitive(i32, len=2)
389    ///   y: vortex.primitive(i32, len=2)
390    /// ";
391    /// assert_eq!(format!("{}", array.display_tree_encodings_only()), expected);
392    /// ```
393    pub fn display_tree_encodings_only(&self) -> impl Display {
394        DisplayArrayAs(
395            self,
396            DisplayOptions::TreeDisplay {
397                buffers: false,
398                metadata: false,
399                stats: false,
400            },
401        )
402    }
403
404    /// Display the tree of encodings of this array as an indented lists.
405    ///
406    /// While some metadata (such as length, bytes and validity-rate) are included, the logical
407    /// values of the array are not displayed. To view the logical values see
408    /// [Array::display_as](../trait.Array.html#method.display_as)
409    /// and [DisplayOptions].
410    ///
411    /// # Examples
412    /// ```
413    /// # use vortex_array::display::DisplayOptions;
414    /// # use vortex_array::IntoArray;
415    /// # use vortex_buffer::buffer;
416    /// let array = buffer![0_i16, 1, 2, 3, 4].into_array();
417    /// let expected = "root: vortex.primitive(i16, len=5) nbytes=10 B (100.00%)
418    ///   metadata: EmptyMetadata
419    ///   buffer: values host 10 B (align=2) (100.00%)
420    /// ";
421    /// assert_eq!(format!("{}", array.display_tree()), expected);
422    /// ```
423    pub fn display_tree(&self) -> impl Display {
424        DisplayArrayAs(
425            self,
426            DisplayOptions::TreeDisplay {
427                buffers: true,
428                metadata: true,
429                stats: true,
430            },
431        )
432    }
433
434    /// Display the array as a formatted table.
435    ///
436    /// For struct arrays, displays a column for each field in the struct.
437    /// For regular arrays, displays a single column with values.
438    ///
439    /// # Examples
440    /// ```
441    /// # #[cfg(feature = "table-display")]
442    /// # {
443    /// # use vortex_array::arrays::StructArray;
444    /// # use vortex_array::IntoArray;
445    /// # use vortex_buffer::buffer;
446    /// let s = StructArray::from_fields(&[
447    ///     ("x", buffer![1, 2].into_array()),
448    ///     ("y", buffer![3, 4].into_array()),
449    /// ]).unwrap().into_array();
450    /// let expected = "
451    /// ┌──────┬──────┐
452    /// │  x   │  y   │
453    /// ├──────┼──────┤
454    /// │ 1i32 │ 3i32 │
455    /// ├──────┼──────┤
456    /// │ 2i32 │ 4i32 │
457    /// └──────┴──────┘".trim();
458    /// assert_eq!(format!("{}", s.display_table()), expected);
459    /// # }
460    /// ```
461    #[cfg(feature = "table-display")]
462    pub fn display_table(&self) -> impl Display {
463        DisplayArrayAs(self, DisplayOptions::TableDisplay)
464    }
465
466    fn fmt_as(&self, f: &mut std::fmt::Formatter, options: &DisplayOptions) -> std::fmt::Result {
467        match options {
468            DisplayOptions::MetadataOnly => {
469                write!(
470                    f,
471                    "{}({}, len={})",
472                    self.encoding_id(),
473                    self.dtype(),
474                    self.len()
475                )
476            }
477            DisplayOptions::CommaSeparatedScalars {
478                omit_comma_after_space,
479            } => {
480                write!(f, "{}", if f.alternate() { "[\n" } else { "[" })?;
481                let sep = if *omit_comma_after_space { "," } else { ", " };
482                let sep = if f.alternate() { ",\n" } else { sep };
483                let limit = std::cmp::min(self.len(), f.precision().unwrap_or(DISPLAY_LIMIT));
484                write!(
485                    f,
486                    "{}",
487                    (0..limit)
488                        .map(|i| self
489                            .scalar_at(i)
490                            .map_or_else(|e| format!("<error: {e}>"), |s| s.to_string()))
491                        .format(sep)
492                )?;
493                write!(f, "{}", if f.alternate() { "\n]" } else { "]" })
494            }
495            DisplayOptions::TreeDisplay {
496                buffers,
497                metadata,
498                stats,
499            } => {
500                write!(
501                    f,
502                    "{}",
503                    TreeDisplayWrapper {
504                        array: self.to_array(),
505                        buffers: *buffers,
506                        metadata: *metadata,
507                        stats: *stats
508                    }
509                )
510            }
511            #[cfg(feature = "table-display")]
512            DisplayOptions::TableDisplay => {
513                use crate::canonical::ToCanonical;
514                use crate::dtype::DType;
515
516                let mut builder = tabled::builder::Builder::default();
517
518                // Special logic for struct arrays.
519                let DType::Struct(sf, _) = self.dtype() else {
520                    // For non-struct arrays, simply display a single column table without header.
521                    for row_idx in 0..self.len() {
522                        let value = self
523                            .scalar_at(row_idx)
524                            .map_or_else(|e| format!("<error: {e}>"), |s| s.to_string());
525                        builder.push_record([value]);
526                    }
527
528                    let mut table = builder.build();
529                    table.with(tabled::settings::Style::modern());
530
531                    return write!(f, "{table}");
532                };
533
534                let struct_ = self.to_struct();
535                builder.push_record(sf.names().iter().map(|name| name.to_string()));
536
537                for row_idx in 0..self.len() {
538                    if !self.is_valid(row_idx).unwrap_or(false) {
539                        let null_row = vec!["null".to_string(); sf.names().len()];
540                        builder.push_record(null_row);
541                    } else {
542                        let mut row = Vec::new();
543                        for field_array in struct_.unmasked_fields().iter() {
544                            let value = field_array
545                                .scalar_at(row_idx)
546                                .map_or_else(|e| format!("<error: {e}>"), |s| s.to_string());
547                            row.push(value);
548                        }
549                        builder.push_record(row);
550                    }
551                }
552
553                let mut table = builder.build();
554                table.with(tabled::settings::Style::modern());
555
556                // Center headers
557                for col_idx in 0..sf.names().len() {
558                    table.modify((0, col_idx), tabled::settings::Alignment::center());
559                }
560
561                for row_idx in 0..self.len() {
562                    if !self.is_valid(row_idx).unwrap_or(false) {
563                        table.modify(
564                            (1 + row_idx, 0),
565                            tabled::settings::Span::column(sf.names().len() as isize),
566                        );
567                        table.modify((1 + row_idx, 0), tabled::settings::Alignment::center());
568                    }
569                }
570
571                write!(f, "{table}")
572            }
573        }
574    }
575}
576
577#[cfg(test)]
578mod test {
579    use vortex_buffer::Buffer;
580    use vortex_buffer::buffer;
581
582    use crate::IntoArray as _;
583    use crate::arrays::BoolArray;
584    use crate::arrays::ListArray;
585    use crate::arrays::StructArray;
586    use crate::dtype::FieldNames;
587    use crate::validity::Validity;
588
589    #[test]
590    fn test_primitive() {
591        let x = Buffer::<u32>::empty().into_array();
592        assert_eq!(x.display_values().to_string(), "[]");
593
594        let x = buffer![1].into_array();
595        assert_eq!(x.display_values().to_string(), "[1i32]");
596
597        let x = buffer![1, 2, 3, 4].into_array();
598        assert_eq!(x.display_values().to_string(), "[1i32, 2i32, 3i32, 4i32]");
599    }
600
601    #[test]
602    fn test_empty_struct() {
603        let s = StructArray::try_new(
604            FieldNames::empty(),
605            vec![],
606            3,
607            Validity::Array(BoolArray::from_iter([true, false, true]).into_array()),
608        )
609        .unwrap()
610        .into_array();
611        assert_eq!(s.display_values().to_string(), "[{}, null, {}]");
612    }
613
614    #[test]
615    fn test_simple_struct() {
616        let s = StructArray::from_fields(&[
617            ("x", buffer![1, 2, 3, 4].into_array()),
618            ("y", buffer![-1, -2, -3, -4].into_array()),
619        ])
620        .unwrap()
621        .into_array();
622        assert_eq!(
623            s.display_values().to_string(),
624            "[{x: 1i32, y: -1i32}, {x: 2i32, y: -2i32}, {x: 3i32, y: -3i32}, {x: 4i32, y: -4i32}]"
625        );
626    }
627
628    #[test]
629    fn test_list() {
630        let x = ListArray::try_new(
631            buffer![1, 2, 3, 4].into_array(),
632            buffer![0, 0, 1, 1, 2, 4].into_array(),
633            Validity::Array(BoolArray::from_iter([true, true, false, true, true]).into_array()),
634        )
635        .unwrap()
636        .into_array();
637        assert_eq!(
638            x.display_values().to_string(),
639            "[[], [1i32], null, [2i32], [3i32, 4i32]]"
640        );
641    }
642
643    #[test]
644    fn test_table_display_primitive() {
645        use crate::display::DisplayOptions;
646
647        let array = buffer![1, 2, 3, 4].into_array();
648        let table_display = array.display_as(DisplayOptions::TableDisplay);
649        assert_eq!(
650            table_display.to_string(),
651            r"
652┌──────┐
653│ 1i32 │
654├──────┤
655│ 2i32 │
656├──────┤
657│ 3i32 │
658├──────┤
659│ 4i32 │
660└──────┘"
661                .trim()
662        );
663    }
664
665    #[test]
666    fn test_table_display() {
667        use crate::display::DisplayOptions;
668
669        let array = crate::arrays::PrimitiveArray::from_option_iter(vec![
670            Some(-1),
671            Some(-2),
672            Some(-3),
673            None,
674        ])
675        .into_array();
676
677        let struct_ = StructArray::try_from_iter_with_validity(
678            [("x", buffer![1, 2, 3, 4].into_array()), ("y", array)],
679            Validity::Array(BoolArray::from_iter([true, false, true, true]).into_array()),
680        )
681        .unwrap()
682        .into_array();
683
684        let table_display = struct_.display_as(DisplayOptions::TableDisplay);
685        assert_eq!(
686            table_display.to_string(),
687            r"
688┌──────┬───────┐
689│  x   │   y   │
690├──────┼───────┤
691│ 1i32 │ -1i32 │
692├──────┼───────┤
693│     null     │
694├──────┼───────┤
695│ 3i32 │ -3i32 │
696├──────┼───────┤
697│ 4i32 │ null  │
698└──────┴───────┘"
699                .trim()
700        );
701    }
702}