## Coverage Report

#### Created: 2025-11-17 14:14

next uncovered line (L), next uncovered region (R), next uncovered branch (B)

    /Users/andrewlamb/Software/arrow-rs/arrow-schema/src/datatype_display.rs

    Line
    Count
    Source
    1
    // Licensed to the Apache Software Foundation (ASF) under one
    2
    // or more contributor license agreements.  See the NOTICE file
    3
    // distributed with this work for additional information
    4
    // regarding copyright ownership.  The ASF licenses this file
    5
    // to you under the Apache License, Version 2.0 (the
    6
    // "License"); you may not use this file except in compliance
    7
    // with the License.  You may obtain a copy of the License at
    8
    //
    9
    //   http://www.apache.org/licenses/LICENSE-2.0
    10
    //
    11
    // Unless required by applicable law or agreed to in writing,
    12
    // software distributed under the License is distributed on an
    13
    // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    14
    // KIND, either express or implied.  See the License for the
    15
    // specific language governing permissions and limitations
    16
    // under the License.
    17
    18
    use std::{collections::HashMap, fmt};
    19
    20
    use crate::DataType;
    21
    22
    impl fmt::Display for DataType {
    23
    36
        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    24
    0
            fn format_metadata(metadata: &HashMap<String, String>) -> String {
    25
    0
                format!("{}", FormatMetadata(metadata))
    26
    0
            }
    27
    28
    0
            fn format_field(field: &crate::Field) -> String {
    29
    0
                let name = field.name();
    30
    0
                let maybe_nullable = if field.is_nullable() { "nullable " } else { "" };
    31
    0
                let data_type = field.data_type();
    32
    0
                let metadata_str = format_metadata(field.metadata());
    33
    0
                format!("{name:?}: {maybe_nullable}{data_type}{metadata_str}")
    34
    0
            }
    35
    36
            // A lot of these can still be improved a lot.
    37
            // _Some_ of these can be parsed with `FromStr`, but not all (YET!).
    38
            // The goal is that the formatting should always be
    39
            // * Terse and teadable
    40
            // * Reversible (contain all necessary information to reverse it perfectly)
    41
    42
    36
            match &self {
    43
    0
                Self::Null => write!(f, "Null"),
    44
    0
                Self::Boolean => write!(f, "Boolean"),
    45
    3
                Self::Int8 => write!(f, "Int8"),
    46
    3
                Self::Int16 => write!(f, "Int16"),
    47
    5
                Self::Int32 => write!(f, "Int32"),
    48
    5
                Self::Int64 => write!(f, "Int64"),
    49
    3
                Self::UInt8 => write!(f, "UInt8"),
    50
    3
                Self::UInt16 => write!(f, "UInt16"),
    51
    3
                Self::UInt32 => write!(f, "UInt32"),
    52
    3
                Self::UInt64 => write!(f, "UInt64"),
    53
    0
                Self::Float16 => write!(f, "Float16"),
    54
    3
                Self::Float32 => write!(f, "Float32"),
    55
    0
                Self::Float64 => write!(f, "Float64"),
    56
    0
                Self::Timestamp(time_unit, timezone) => {
    57
    0
                    if let Some(timezone) = timezone {
    58
    0
                        write!(f, "Timestamp({time_unit}, {timezone:?})")
    59
                    } else {
    60
    0
                        write!(f, "Timestamp({time_unit})")
    61
                    }
    62
                }
    63
    0
                Self::Date32 => write!(f, "Date32"),
    64
    0
                Self::Date64 => write!(f, "Date64"),
    65
    0
                Self::Time32(time_unit) => write!(f, "Time32({time_unit})"),
    66
    0
                Self::Time64(time_unit) => write!(f, "Time64({time_unit})"),
    67
    0
                Self::Duration(time_unit) => write!(f, "Duration({time_unit})"),
    68
    0
                Self::Interval(interval_unit) => write!(f, "Interval({interval_unit:?})"),
    69
    0
                Self::Binary => write!(f, "Binary"),
    70
    0
                Self::FixedSizeBinary(bytes_per_value) => {
    71
    0
                    write!(f, "FixedSizeBinary({bytes_per_value:?})")
    72
                }
    73
    0
                Self::LargeBinary => write!(f, "LargeBinary"),
    74
    0
                Self::BinaryView => write!(f, "BinaryView"),
    75
    5
                Self::Utf8 => write!(f, "Utf8"),
    76
    0
                Self::LargeUtf8 => write!(f, "LargeUtf8"),
    77
    0
                Self::Utf8View => write!(f, "Utf8View"),
    78
    0
                Self::List(field)
    79
    0
                | Self::LargeList(field)
    80
    0
                | Self::ListView(field)
    81
    0
                | Self::LargeListView(field) => {
    82
    0
                    let type_name = if matches!(self, Self::List(_)) {
    83
    0
                        "List"
    84
    0
                    } else if matches!(self, Self::ListView(_)) {
    85
    0
                        "ListView"
    86
    0
                    } else if matches!(self, Self::LargeList(_)) {
    87
    0
                        "LargeList"
    88
                    } else {
    89
    0
                        "LargeListView"
    90
                    };
    91
    92
    0
                    let name = field.name();
    93
    0
                    let maybe_nullable = if field.is_nullable() { "nullable " } else { "" };
    94
    0
                    let data_type = field.data_type();
    95
    0
                    let field_name_str = if name == "item" {
    96
    0
                        String::default()
    97
                    } else {
    98
    0
                        format!(", field: '{name}'")
    99
                    };
    100
    0
                    let metadata_str = format_metadata(field.metadata());
    101
    102
                    // e.g. `LargeList(nullable Uint32)
    103
    0
                    write!(
    104
    0
                        f,
    105
    0
                        "{type_name}({maybe_nullable}{data_type}{field_name_str}{metadata_str})"
    106
                    )
    107
                }
    108
    0
                Self::FixedSizeList(field, size) => {
    109
    0
                    let name = field.name();
    110
    0
                    let maybe_nullable = if field.is_nullable() { "nullable " } else { "" };
    111
    0
                    let data_type = field.data_type();
    112
    0
                    let field_name_str = if name == "item" {
    113
    0
                        String::default()
    114
                    } else {
    115
    0
                        format!(", field: '{name}'")
    116
                    };
    117
    0
                    let metadata_str = format_metadata(field.metadata());
    118
    119
    0
                    write!(
    120
    0
                        f,
    121
    0
                        "FixedSizeList({size} x {maybe_nullable}{data_type}{field_name_str}{metadata_str})",
    122
                    )
    123
                }
    124
    0
                Self::Struct(fields) => {
    125
    0
                    write!(f, "Struct(")?;
    126
    0
                    if !fields.is_empty() {
    127
    0
                        let fields_str = fields
    128
    0
                            .iter()
    129
    0
                            .map(|field| format_field(field))
    130
    0
                            .collect::<Vec<_>>()
    131
    0
                            .join(", ");
    132
    0
                        write!(f, "{fields_str}")?;
    133
    0
                    }
    134
    0
                    write!(f, ")")?;
    135
    0
                    Ok(())
    136
                }
    137
    0
                Self::Union(union_fields, union_mode) => {
    138
    0
                    write!(f, "Union({union_mode:?}")?;
    139
    0
                    if !union_fields.is_empty() {
    140
    0
                        write!(f, ", ")?;
    141
    0
                        let fields_str = union_fields
    142
    0
                            .iter()
    143
    0
                            .map(|v| {
    144
    0
                                let type_id = v.0;
    145
    0
                                let field_str = format_field(v.1);
    146
    0
                                format!("{type_id:?}: ({field_str})")
    147
    0
                            })
    148
    0
                            .collect::<Vec<_>>()
    149
    0
                            .join(", ");
    150
    0
                        write!(f, "{fields_str}")?;
    151
    0
                    }
    152
    0
                    write!(f, ")")?;
    153
    0
                    Ok(())
    154
                }
    155
    0
                Self::Dictionary(data_type, data_type1) => {
    156
    0
                    write!(f, "Dictionary({data_type}, {data_type1})")
    157
                }
    158
    0
                Self::Decimal32(precision, scale) => write!(f, "Decimal32({precision}, {scale})"),
    159
    0
                Self::Decimal64(precision, scale) => write!(f, "Decimal64({precision}, {scale})"),
    160
    0
                Self::Decimal128(precision, scale) => write!(f, "Decimal128({precision}, {scale})"),
    161
    0
                Self::Decimal256(precision, scale) => write!(f, "Decimal256({precision}, {scale})"),
    162
    0
                Self::Map(field, sorted) => {
    163
    0
                    write!(f, "Map(")?;
    164
    0
                    let map_field_str = format_field(field);
    165
    0
                    let keys_are_sorted = if *sorted { "sorted" } else { "unsorted" };
    166
    167
    0
                    write!(f, "{map_field_str}, {keys_are_sorted})")?;
    168
    0
                    Ok(())
    169
                }
    170
    0
                Self::RunEndEncoded(run_ends_field, values_field) => {
    171
    0
                    write!(f, "RunEndEncoded(")?;
    172
    0
                    let run_ends_str = format_field(run_ends_field);
    173
    0
                    let values_str = format_field(values_field);
    174
    175
    0
                    write!(f, "{run_ends_str}, {values_str})")?;
    176
    0
                    Ok(())
    177
                }
    178
            }
    179
    36
        }
    180
    }
    181
    182
    /// Adapter to format a metadata HashMap consistently.
    183
    struct FormatMetadata<'a>(&'a HashMap<String, String>);
    184
    185
    impl fmt::Display for FormatMetadata<'_> {
    186
    0
        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    187
    0
            let metadata = self.0;
    188
    0
            if metadata.is_empty() {
    189
    0
                Ok(())
    190
            } else {
    191
    0
                let mut entries: Vec<(&String, &String)> = metadata.iter().collect();
    192
    0
                entries.sort_by(|a, b| a.0.cmp(b.0));
    193
    0
                write!(f, ", metadata: ")?;
    194
    0
                f.debug_map().entries(entries).finish()
    195
            }
    196
    0
        }
    197
    }
    198
    199
    #[cfg(test)]
    200
    mod tests {
    201
    202
        use std::sync::Arc;
    203
    204
        use crate::Field;
    205
    206
        use super::*;
    207
    208
        #[test]
    209
        fn test_display_list() {
    210
            let list_data_type = DataType::List(Arc::new(Field::new_list_field(DataType::Int32, true)));
    211
            let list_data_type_string = list_data_type.to_string();
    212
            let expected_string = "List(nullable Int32)";
    213
            assert_eq!(list_data_type_string, expected_string);
    214
        }
    215
    216
        #[test]
    217
        fn test_display_list_view() {
    218
            let list_view_data_type =
    219
                DataType::ListView(Arc::new(Field::new("item", DataType::Int32, true)));
    220
            let list_view_data_type_string = list_view_data_type.to_string();
    221
            let expected_string = "ListView(nullable Int32)";
    222
            assert_eq!(list_view_data_type_string, expected_string);
    223
        }
    224
    225
        #[test]
    226
        fn test_display_list_with_named_field() {
    227
            let list_data_type = DataType::List(Arc::new(Field::new("foo", DataType::UInt64, false)));
    228
            let list_data_type_string = list_data_type.to_string();
    229
            let expected_string = "List(UInt64, field: 'foo')";
    230
            assert_eq!(list_data_type_string, expected_string);
    231
        }
    232
    233
        #[test]
    234
        fn test_display_list_view_with_named_field() {
    235
            let list_view_data_type =
    236
                DataType::ListView(Arc::new(Field::new("bar", DataType::UInt64, false)));
    237
            let list_view_data_type_string = list_view_data_type.to_string();
    238
            let expected_string = "ListView(UInt64, field: 'bar')";
    239
            assert_eq!(list_view_data_type_string, expected_string);
    240
        }
    241
    242
        #[test]
    243
        fn test_display_nested_list() {
    244
            let nested_data_type = DataType::List(Arc::new(Field::new_list_field(
    245
                DataType::List(Arc::new(Field::new_list_field(DataType::UInt64, false))),
    246
                false,
    247
            )));
    248
            let nested_data_type_string = nested_data_type.to_string();
    249
            let nested_expected_string = "List(List(UInt64))";
    250
            assert_eq!(nested_data_type_string, nested_expected_string);
    251
        }
    252
    253
        #[test]
    254
        fn test_display_nested_list_view() {
    255
            let nested_view_data_type = DataType::ListView(Arc::new(Field::new_list_field(
    256
                DataType::ListView(Arc::new(Field::new_list_field(DataType::UInt64, false))),
    257
                false,
    258
            )));
    259
            let nested_view_data_type_string = nested_view_data_type.to_string();
    260
            let nested_view_expected_string = "ListView(ListView(UInt64))";
    261
            assert_eq!(nested_view_data_type_string, nested_view_expected_string);
    262
        }
    263
    264
        #[test]
    265
        fn test_display_list_with_metadata() {
    266
            let mut field = Field::new_list_field(DataType::Int32, true);
    267
            let metadata = HashMap::from([("foo1".to_string(), "value1".to_string())]);
    268
            field.set_metadata(metadata);
    269
            let list_data_type = DataType::List(Arc::new(field));
    270
            let list_data_type_string = list_data_type.to_string();
    271
            let expected_string = "List(nullable Int32, metadata: {\"foo1\": \"value1\"})";
    272
    273
            assert_eq!(list_data_type_string, expected_string);
    274
        }
    275
    276
        #[test]
    277
        fn test_display_list_view_with_metadata() {
    278
            let mut field = Field::new_list_field(DataType::Int32, true);
    279
            let metadata = HashMap::from([("foo2".to_string(), "value2".to_string())]);
    280
            field.set_metadata(metadata);
    281
            let list_view_data_type = DataType::ListView(Arc::new(field));
    282
            let list_view_data_type_string = list_view_data_type.to_string();
    283
            let expected_string = "ListView(nullable Int32, metadata: {\"foo2\": \"value2\"})";
    284
            assert_eq!(list_view_data_type_string, expected_string);
    285
        }
    286
    287
        #[test]
    288
        fn test_display_large_list() {
    289
            let large_list_data_type =
    290
                DataType::LargeList(Arc::new(Field::new_list_field(DataType::Int32, true)));
    291
            let large_list_data_type_string = large_list_data_type.to_string();
    292
            let expected_string = "LargeList(nullable Int32)";
    293
            assert_eq!(large_list_data_type_string, expected_string);
    294
    295
            // Test with named field
    296
            let large_list_named =
    297
                DataType::LargeList(Arc::new(Field::new("bar", DataType::UInt64, false)));
    298
            let large_list_named_string = large_list_named.to_string();
    299
            let expected_named_string = "LargeList(UInt64, field: 'bar')";
    300
            assert_eq!(large_list_named_string, expected_named_string);
    301
    302
            // Test with metadata
    303
            let mut field = Field::new_list_field(DataType::Int32, true);
    304
            let metadata = HashMap::from([("key1".to_string(), "value1".to_string())]);
    305
            field.set_metadata(metadata);
    306
            let large_list_metadata = DataType::LargeList(Arc::new(field));
    307
            let large_list_metadata_string = large_list_metadata.to_string();
    308
            let expected_metadata_string =
    309
                "LargeList(nullable Int32, metadata: {\"key1\": \"value1\"})";
    310
            assert_eq!(large_list_metadata_string, expected_metadata_string);
    311
        }
    312
    313
        #[test]
    314
        fn test_display_large_list_view() {
    315
            let large_list_view_data_type =
    316
                DataType::LargeListView(Arc::new(Field::new("item", DataType::Int32, true)));
    317
            let large_list_view_data_type_string = large_list_view_data_type.to_string();
    318
            let expected_string = "LargeListView(nullable Int32)";
    319
            assert_eq!(large_list_view_data_type_string, expected_string);
    320
    321
            // Test with named field
    322
            let large_list_view_named =
    323
                DataType::LargeListView(Arc::new(Field::new("bar", DataType::UInt64, false)));
    324
            let large_list_view_named_string = large_list_view_named.to_string();
    325
            let expected_named_string = "LargeListView(UInt64, field: 'bar')";
    326
            assert_eq!(large_list_view_named_string, expected_named_string);
    327
    328
            // Test with metadata
    329
            let mut field = Field::new_list_field(DataType::Int32, true);
    330
            let metadata = HashMap::from([("key1".to_string(), "value1".to_string())]);
    331
            field.set_metadata(metadata);
    332
            let large_list_view_metadata = DataType::LargeListView(Arc::new(field));
    333
            let large_list_view_metadata_string = large_list_view_metadata.to_string();
    334
            let expected_metadata_string =
    335
                "LargeListView(nullable Int32, metadata: {\"key1\": \"value1\"})";
    336
            assert_eq!(large_list_view_metadata_string, expected_metadata_string);
    337
        }
    338
    339
        #[test]
    340
        fn test_display_fixed_size_list() {
    341
            let fixed_size_list =
    342
                DataType::FixedSizeList(Arc::new(Field::new_list_field(DataType::Int32, true)), 5);
    343
            let fixed_size_list_string = fixed_size_list.to_string();
    344
            let expected_string = "FixedSizeList(5 x nullable Int32)";
    345
            assert_eq!(fixed_size_list_string, expected_string);
    346
    347
            // Test with named field
    348
            let fixed_size_named =
    349
                DataType::FixedSizeList(Arc::new(Field::new("baz", DataType::UInt64, false)), 3);
    350
            let fixed_size_named_string = fixed_size_named.to_string();
    351
            let expected_named_string = "FixedSizeList(3 x UInt64, field: 'baz')";
    352
            assert_eq!(fixed_size_named_string, expected_named_string);
    353
    354
            // Test with metadata
    355
            let mut field = Field::new_list_field(DataType::Int32, true);
    356
            let metadata = HashMap::from([("key2".to_string(), "value2".to_string())]);
    357
            field.set_metadata(metadata);
    358
            let fixed_size_metadata = DataType::FixedSizeList(Arc::new(field), 4);
    359
            let fixed_size_metadata_string = fixed_size_metadata.to_string();
    360
            let expected_metadata_string =
    361
                "FixedSizeList(4 x nullable Int32, metadata: {\"key2\": \"value2\"})";
    362
            assert_eq!(fixed_size_metadata_string, expected_metadata_string);
    363
        }
    364
    365
        #[test]
    366
        fn test_display_struct() {
    367
            let fields = vec![
    368
                Field::new("a", DataType::Int32, false),
    369
                Field::new("b", DataType::Utf8, true),
    370
            ];
    371
            let struct_data_type = DataType::Struct(fields.into());
    372
            let struct_data_type_string = struct_data_type.to_string();
    373
            let expected_string = "Struct(\"a\": Int32, \"b\": nullable Utf8)";
    374
            assert_eq!(struct_data_type_string, expected_string);
    375
    376
            // Test with metadata
    377
            let mut field_with_metadata = Field::new("b", DataType::Utf8, true);
    378
            let metadata = HashMap::from([
    379
                ("key".to_string(), "value".to_string()),
    380
                ("key2".to_string(), "value2".to_string()),
    381
            ]);
    382
            field_with_metadata.set_metadata(metadata);
    383
            let struct_fields_with_metadata =
    384
                vec![Field::new("a", DataType::Int32, false), field_with_metadata];
    385
            let struct_data_type_with_metadata = DataType::Struct(struct_fields_with_metadata.into());
    386
            let struct_data_type_with_metadata_string = struct_data_type_with_metadata.to_string();
    387
            let expected_string_with_metadata = "Struct(\"a\": Int32, \"b\": nullable Utf8, metadata: {\"key\": \"value\", \"key2\": \"value2\"})";
    388
            assert_eq!(
    389
                struct_data_type_with_metadata_string,
    390
                expected_string_with_metadata
    391
            );
    392
        }
    393
    394
        #[test]
    395
        fn test_display_union() {
    396
            let fields = vec![
    397
                Field::new("a", DataType::Int32, false),
    398
                Field::new("b", DataType::Utf8, true),
    399
            ];
    400
            let type_ids = vec![0, 1];
    401
            let union_fields = type_ids
    402
                .into_iter()
    403
                .zip(fields.into_iter().map(Arc::new))
    404
                .collect();
    405
    406
            let union_data_type = DataType::Union(union_fields, crate::UnionMode::Sparse);
    407
            let union_data_type_string = union_data_type.to_string();
    408
            let expected_string = "Union(Sparse, 0: (\"a\": Int32), 1: (\"b\": nullable Utf8))";
    409
            assert_eq!(union_data_type_string, expected_string);
    410
    411
            // Test with metadata
    412
            let mut field_with_metadata = Field::new("b", DataType::Utf8, true);
    413
            let metadata = HashMap::from([("key".to_string(), "value".to_string())]);
    414
            field_with_metadata.set_metadata(metadata);
    415
            let union_fields_with_metadata = vec![
    416
                (0, Arc::new(Field::new("a", DataType::Int32, false))),
    417
                (1, Arc::new(field_with_metadata)),
    418
            ]
    419
            .into_iter()
    420
            .collect();
    421
            let union_data_type_with_metadata =
    422
                DataType::Union(union_fields_with_metadata, crate::UnionMode::Sparse);
    423
            let union_data_type_with_metadata_string = union_data_type_with_metadata.to_string();
    424
            let expected_string_with_metadata = "Union(Sparse, 0: (\"a\": Int32), 1: (\"b\": nullable Utf8, metadata: {\"key\": \"value\"}))";
    425
            assert_eq!(
    426
                union_data_type_with_metadata_string,
    427
                expected_string_with_metadata
    428
            );
    429
        }
    430
    431
        #[test]
    432
        fn test_display_map() {
    433
            let entry_field = Field::new(
    434
                "entries",
    435
                DataType::Struct(
    436
                    vec![
    437
                        Field::new("key", DataType::Utf8, false),
    438
                        Field::new("value", DataType::Int32, true),
    439
                    ]
    440
                    .into(),
    441
                ),
    442
                false,
    443
            );
    444
            let map_data_type = DataType::Map(Arc::new(entry_field), true);
    445
            let map_data_type_string = map_data_type.to_string();
    446
            let expected_string =
    447
                "Map(\"entries\": Struct(\"key\": Utf8, \"value\": nullable Int32), sorted)";
    448
            assert_eq!(map_data_type_string, expected_string);
    449
    450
            // Test with metadata
    451
            let mut entry_field_with_metadata = Field::new(
    452
                "entries",
    453
                DataType::Struct(
    454
                    vec![
    455
                        Field::new("key", DataType::Utf8, false),
    456
                        Field::new("value", DataType::Int32, true),
    457
                    ]
    458
                    .into(),
    459
                ),
    460
                false,
    461
            );
    462
            let metadata = HashMap::from([("key".to_string(), "value".to_string())]);
    463
            entry_field_with_metadata.set_metadata(metadata);
    464
            let map_data_type_with_metadata = DataType::Map(Arc::new(entry_field_with_metadata), true);
    465
            let map_data_type_with_metadata_string = map_data_type_with_metadata.to_string();
    466
            let expected_string_with_metadata = "Map(\"entries\": Struct(\"key\": Utf8, \"value\": nullable Int32), metadata: {\"key\": \"value\"}, sorted)";
    467
            assert_eq!(
    468
                map_data_type_with_metadata_string,
    469
                expected_string_with_metadata
    470
            );
    471
        }
    472
    473
        #[test]
    474
        fn test_display_run_end_encoded() {
    475
            let run_ends_field = Arc::new(Field::new("run_ends", DataType::UInt32, false));
    476
            let values_field = Arc::new(Field::new("values", DataType::Int32, true));
    477
            let ree_data_type = DataType::RunEndEncoded(run_ends_field.clone(), values_field.clone());
    478
            let ree_data_type_string = ree_data_type.to_string();
    479
            let expected_string = "RunEndEncoded(\"run_ends\": UInt32, \"values\": nullable Int32)";
    480
            assert_eq!(ree_data_type_string, expected_string);
    481
    482
            // Test with metadata
    483
            let mut run_ends_field_with_metadata = Field::new("run_ends", DataType::UInt32, false);
    484
            let metadata = HashMap::from([("key".to_string(), "value".to_string())]);
    485
            run_ends_field_with_metadata.set_metadata(metadata);
    486
            let ree_data_type_with_metadata =
    487
                DataType::RunEndEncoded(Arc::new(run_ends_field_with_metadata), values_field.clone());
    488
            let ree_data_type_with_metadata_string = ree_data_type_with_metadata.to_string();
    489
            let expected_string_with_metadata = "RunEndEncoded(\"run_ends\": UInt32, metadata: {\"key\": \"value\"}, \"values\": nullable Int32)";
    490
            assert_eq!(
    491
                ree_data_type_with_metadata_string,
    492
                expected_string_with_metadata
    493
            );
    494
        }
    495
    496
        #[test]
    497
        fn test_display_dictionary() {
    498
            let dict_data_type =
    499
                DataType::Dictionary(Box::new(DataType::Int8), Box::new(DataType::Utf8));
    500
            let dict_data_type_string = dict_data_type.to_string();
    501
            let expected_string = "Dictionary(Int8, Utf8)";
    502
            assert_eq!(dict_data_type_string, expected_string);
    503
    504
            // Test with complex index and value types
    505
            let complex_dict_data_type = DataType::Dictionary(
    506
                Box::new(DataType::Int16),
    507
                Box::new(DataType::Struct(
    508
                    vec![
    509
                        Field::new("a", DataType::Int32, false),
    510
                        Field::new("b", DataType::Utf8, true),
    511
                    ]
    512
                    .into(),
    513
                )),
    514
            );
    515
            let complex_dict_data_type_string = complex_dict_data_type.to_string();
    516
            let expected_complex_string =
    517
                "Dictionary(Int16, Struct(\"a\": Int32, \"b\": nullable Utf8))";
    518
            assert_eq!(complex_dict_data_type_string, expected_complex_string);
    519
        }
    520
    521
        #[test]
    522
        fn test_display_interval() {
    523
            let interval_year_month = DataType::Interval(crate::IntervalUnit::YearMonth);
    524
            let interval_year_month_string = interval_year_month.to_string();
    525
            let expected_year_month_string = "Interval(YearMonth)";
    526
            assert_eq!(interval_year_month_string, expected_year_month_string);
    527
    528
            let interval_day_time = DataType::Interval(crate::IntervalUnit::DayTime);
    529
            let interval_day_time_string = interval_day_time.to_string();
    530
            let expected_day_time_string = "Interval(DayTime)";
    531
            assert_eq!(interval_day_time_string, expected_day_time_string);
    532
    533
            let interval_month_day_nano = DataType::Interval(crate::IntervalUnit::MonthDayNano);
    534
            let interval_month_day_nano_string = interval_month_day_nano.to_string();
    535
            let expected_month_day_nano_string = "Interval(MonthDayNano)";
    536
            assert_eq!(
    537
                interval_month_day_nano_string,
    538
                expected_month_day_nano_string
    539
            );
    540
        }
    541
    542
        #[test]
    543
        fn test_display_timestamp() {
    544
            let timestamp_without_tz = DataType::Timestamp(crate::TimeUnit::Microsecond, None);
    545
            let timestamp_without_tz_string = timestamp_without_tz.to_string();
    546
            let expected_without_tz_string = "Timestamp(µs)";
    547
            assert_eq!(timestamp_without_tz_string, expected_without_tz_string);
    548
    549
            let timestamp_with_tz =
    550
                DataType::Timestamp(crate::TimeUnit::Nanosecond, Some(Arc::from("UTC")));
    551
            let timestamp_with_tz_string = timestamp_with_tz.to_string();
    552
            let expected_with_tz_string = "Timestamp(ns, \"UTC\")";
    553
            assert_eq!(timestamp_with_tz_string, expected_with_tz_string);
    554
        }
    555
    }