## Coverage Report

#### Created: 2025-08-26 07:03

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

    /Users/andrewlamb/Software/arrow-rs/arrow-array/src/cast.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
    //! Defines helper functions for downcasting [`dyn Array`](Array) to concrete types
    19
    20
    use crate::array::*;
    21
    use crate::types::*;
    22
    use arrow_data::ArrayData;
    23
    24
    /// Re-export symbols needed for downcast macros
    25
    ///
    26
    /// Name follows `serde` convention
    27
    #[doc(hidden)]
    28
    pub mod __private {
    29
        pub use arrow_schema::{DataType, IntervalUnit, TimeUnit};
    30
    }
    31
    32
    /// Repeats the provided pattern based on the number of comma separated identifiers
    33
    #[doc(hidden)]
    34
    #[macro_export]
    35
    macro_rules! repeat_pat {
    36
        ($e:pat, $v_:expr) => {
    37
            $e
    38
        };
    39
        ($e:pat, $v_:expr $(, $tail:expr)+) => {
    40
            ($e, $crate::repeat_pat!($e $(, $tail)+))
    41
        }
    42
    }
    43
    44
    /// Given one or more expressions evaluating to an integer [`DataType`] invokes the provided macro
    45
    /// `m` with the corresponding integer [`ArrowPrimitiveType`], followed by any additional arguments
    46
    ///
    47
    /// ```
    48
    /// # use arrow_array::{downcast_primitive, ArrowPrimitiveType, downcast_integer};
    49
    /// # use arrow_schema::DataType;
    50
    ///
    51
    /// macro_rules! dictionary_key_size_helper {
    52
    ///   ($t:ty, $o:ty) => {
    53
    ///       std::mem::size_of::<<$t as ArrowPrimitiveType>::Native>() as $o
    54
    ///   };
    55
    /// }
    56
    ///
    57
    /// fn dictionary_key_size(t: &DataType) -> u8 {
    58
    ///     match t {
    59
    ///         DataType::Dictionary(k, _) => downcast_integer! {
    60
    ///             k.as_ref() => (dictionary_key_size_helper, u8),
    61
    ///             _ => unreachable!(),
    62
    ///         },
    63
    ///         // You can also add a guard to the pattern
    64
    ///         DataType::LargeUtf8 if true => u8::MAX,
    65
    ///         _ => u8::MAX,
    66
    ///     }
    67
    /// }
    68
    ///
    69
    /// assert_eq!(dictionary_key_size(&DataType::Dictionary(Box::new(DataType::Int32), Box::new(DataType::Utf8))), 4);
    70
    /// assert_eq!(dictionary_key_size(&DataType::Dictionary(Box::new(DataType::Int64), Box::new(DataType::Utf8))), 8);
    71
    /// assert_eq!(dictionary_key_size(&DataType::Dictionary(Box::new(DataType::UInt16), Box::new(DataType::Utf8))), 2);
    72
    /// ```
    73
    ///
    74
    /// [`DataType`]: arrow_schema::DataType
    75
    #[macro_export]
    76
    macro_rules! downcast_integer {
    77
        ($($data_type:expr),+ => ($m:path $(, $args:tt)*), $($p:pat $(if $pred:expr)* => $fallback:expr $(,)*)*) => {
    78
            match ($($data_type),+) {
    79
                $crate::repeat_pat!($crate::cast::__private::DataType::Int8, $($data_type),+) => {
    80
                    $m!($crate::types::Int8Type $(, $args)*)
    81
                }
    82
                $crate::repeat_pat!($crate::cast::__private::DataType::Int16, $($data_type),+) => {
    83
                    $m!($crate::types::Int16Type $(, $args)*)
    84
                }
    85
                $crate::repeat_pat!($crate::cast::__private::DataType::Int32, $($data_type),+) => {
    86
                    $m!($crate::types::Int32Type $(, $args)*)
    87
                }
    88
                $crate::repeat_pat!($crate::cast::__private::DataType::Int64, $($data_type),+) => {
    89
                    $m!($crate::types::Int64Type $(, $args)*)
    90
                }
    91
                $crate::repeat_pat!($crate::cast::__private::DataType::UInt8, $($data_type),+) => {
    92
                    $m!($crate::types::UInt8Type $(, $args)*)
    93
                }
    94
                $crate::repeat_pat!($crate::cast::__private::DataType::UInt16, $($data_type),+) => {
    95
                    $m!($crate::types::UInt16Type $(, $args)*)
    96
                }
    97
                $crate::repeat_pat!($crate::cast::__private::DataType::UInt32, $($data_type),+) => {
    98
                    $m!($crate::types::UInt32Type $(, $args)*)
    99
                }
    100
                $crate::repeat_pat!($crate::cast::__private::DataType::UInt64, $($data_type),+) => {
    101
                    $m!($crate::types::UInt64Type $(, $args)*)
    102
                }
    103
                $($p $(if $pred)* => $fallback,)*
    104
            }
    105
        };
    106
    }
    107
    108
    /// Given one or more expressions evaluating to an integer [`PrimitiveArray`] invokes the provided macro
    109
    /// with the corresponding array, along with match statements for any non integer array types
    110
    ///
    111
    /// ```
    112
    /// # use arrow_array::{Array, downcast_integer_array, cast::as_string_array, cast::as_largestring_array};
    113
    /// # use arrow_schema::DataType;
    114
    ///
    115
    /// fn print_integer(array: &dyn Array) {
    116
    ///     downcast_integer_array!(
    117
    ///         array => {
    118
    ///             for v in array {
    119
    ///                 println!("{:?}", v);
    120
    ///             }
    121
    ///         }
    122
    ///         DataType::Utf8 => {
    123
    ///             for v in as_string_array(array) {
    124
    ///                 println!("{:?}", v);
    125
    ///             }
    126
    ///         }
    127
    ///         // You can also add a guard to the pattern
    128
    ///         DataType::LargeUtf8 if true => {
    129
    ///             for v in as_largestring_array(array) {
    130
    ///                 println!("{:?}", v);
    131
    ///             }
    132
    ///         }
    133
    ///         t => println!("Unsupported datatype {}", t)
    134
    ///     )
    135
    /// }
    136
    /// ```
    137
    ///
    138
    /// [`DataType`]: arrow_schema::DataType
    139
    #[macro_export]
    140
    macro_rules! downcast_integer_array {
    141
        ($values:ident => $e:expr, $($p:pat $(if $pred:expr)* => $fallback:expr $(,)*)*) => {
    142
            $crate::downcast_integer_array!($values => {$e} $($p $(if $pred)* => $fallback)*)
    143
        };
    144
        (($($values:ident),+) => $e:expr, $($p:pat $(if $pred:expr)* => $fallback:expr $(,)*)*) => {
    145
            $crate::downcast_integer_array!($($values),+ => {$e} $($p $(if $pred)* => $fallback)*)
    146
        };
    147
        ($($values:ident),+ => $e:block $($p:pat $(if $pred:expr)* => $fallback:expr $(,)*)*) => {
    148
            $crate::downcast_integer_array!(($($values),+) => $e $($p $(if $pred)* => $fallback)*)
    149
        };
    150
        (($($values:ident),+) => $e:block $($p:pat $(if $pred:expr)* => $fallback:expr $(,)*)*) => {
    151
            $crate::downcast_integer!{
    152
                $($values.data_type()),+ => ($crate::downcast_primitive_array_helper, $($values),+, $e),
    153
                $($p $(if $pred)* => $fallback,)*
    154
            }
    155
        };
    156
    }
    157
    158
    /// Given one or more expressions evaluating to an integer [`DataType`] invokes the provided macro
    159
    /// `m` with the corresponding integer [`RunEndIndexType`], followed by any additional arguments
    160
    ///
    161
    /// ```
    162
    /// # use std::sync::Arc;
    163
    /// # use arrow_array::{downcast_primitive, ArrowPrimitiveType, downcast_run_end_index};
    164
    /// # use arrow_schema::{DataType, Field};
    165
    ///
    166
    /// macro_rules! run_end_size_helper {
    167
    ///   ($t:ty, $o:ty) => {
    168
    ///       std::mem::size_of::<<$t as ArrowPrimitiveType>::Native>() as $o
    169
    ///   };
    170
    /// }
    171
    ///
    172
    /// fn run_end_index_size(t: &DataType) -> u8 {
    173
    ///     match t {
    174
    ///         DataType::RunEndEncoded(k, _) => downcast_run_end_index! {
    175
    ///             k.data_type() => (run_end_size_helper, u8),
    176
    ///             _ => unreachable!(),
    177
    ///         },
    178
    ///         // You can also add a guard to the pattern
    179
    ///         DataType::LargeUtf8 if true => u8::MAX,
    180
    ///         _ => u8::MAX,
    181
    ///     }
    182
    /// }
    183
    ///
    184
    /// assert_eq!(run_end_index_size(&DataType::RunEndEncoded(Arc::new(Field::new("a", DataType::Int32, false)), Arc::new(Field::new("b", DataType::Utf8, true)))), 4);
    185
    /// assert_eq!(run_end_index_size(&DataType::RunEndEncoded(Arc::new(Field::new("a", DataType::Int64, false)), Arc::new(Field::new("b", DataType::Utf8, true)))), 8);
    186
    /// assert_eq!(run_end_index_size(&DataType::RunEndEncoded(Arc::new(Field::new("a", DataType::Int16, false)), Arc::new(Field::new("b", DataType::Utf8, true)))), 2);
    187
    /// ```
    188
    ///
    189
    /// [`DataType`]: arrow_schema::DataType
    190
    #[macro_export]
    191
    macro_rules! downcast_run_end_index {
    192
        ($($data_type:expr),+ => ($m:path $(, $args:tt)*), $($p:pat $(if $pred:expr)* => $fallback:expr $(,)*)*) => {
    193
            match ($($data_type),+) {
    194
                $crate::repeat_pat!($crate::cast::__private::DataType::Int16, $($data_type),+) => {
    195
                    $m!($crate::types::Int16Type $(, $args)*)
    196
                }
    197
                $crate::repeat_pat!($crate::cast::__private::DataType::Int32, $($data_type),+) => {
    198
                    $m!($crate::types::Int32Type $(, $args)*)
    199
                }
    200
                $crate::repeat_pat!($crate::cast::__private::DataType::Int64, $($data_type),+) => {
    201
                    $m!($crate::types::Int64Type $(, $args)*)
    202
                }
    203
                $($p $(if $pred)* => $fallback,)*
    204
            }
    205
        };
    206
    }
    207
    208
    /// Given one or more expressions evaluating to primitive [`DataType`] invokes the provided macro
    209
    /// `m` with the corresponding [`ArrowPrimitiveType`], followed by any additional arguments
    210
    ///
    211
    /// ```
    212
    /// # use arrow_array::{downcast_temporal, ArrowPrimitiveType};
    213
    /// # use arrow_schema::DataType;
    214
    ///
    215
    /// macro_rules! temporal_size_helper {
    216
    ///   ($t:ty, $o:ty) => {
    217
    ///       std::mem::size_of::<<$t as ArrowPrimitiveType>::Native>() as $o
    218
    ///   };
    219
    /// }
    220
    ///
    221
    /// fn temporal_size(t: &DataType) -> u8 {
    222
    ///     downcast_temporal! {
    223
    ///         t => (temporal_size_helper, u8),
    224
    ///         // You can also add a guard to the pattern
    225
    ///         DataType::LargeUtf8 if true => u8::MAX,
    226
    ///         _ => u8::MAX
    227
    ///     }
    228
    /// }
    229
    ///
    230
    /// assert_eq!(temporal_size(&DataType::Date32), 4);
    231
    /// assert_eq!(temporal_size(&DataType::Date64), 8);
    232
    /// ```
    233
    ///
    234
    /// [`DataType`]: arrow_schema::DataType
    235
    #[macro_export]
    236
    macro_rules! downcast_temporal {
    237
        ($($data_type:expr),+ => ($m:path $(, $args:tt)*), $($p:pat $(if $pred:expr)* => $fallback:expr $(,)*)*) => {
    238
            match ($($data_type),+) {
    239
                $crate::repeat_pat!($crate::cast::__private::DataType::Time32($crate::cast::__private::TimeUnit::Second), $($data_type),+) => {
    240
                    $m!($crate::types::Time32SecondType $(, $args)*)
    241
                }
    242
                $crate::repeat_pat!($crate::cast::__private::DataType::Time32($crate::cast::__private::TimeUnit::Millisecond), $($data_type),+) => {
    243
                    $m!($crate::types::Time32MillisecondType $(, $args)*)
    244
                }
    245
                $crate::repeat_pat!($crate::cast::__private::DataType::Time64($crate::cast::__private::TimeUnit::Microsecond), $($data_type),+) => {
    246
                    $m!($crate::types::Time64MicrosecondType $(, $args)*)
    247
                }
    248
                $crate::repeat_pat!($crate::cast::__private::DataType::Time64($crate::cast::__private::TimeUnit::Nanosecond), $($data_type),+) => {
    249
                    $m!($crate::types::Time64NanosecondType $(, $args)*)
    250
                }
    251
                $crate::repeat_pat!($crate::cast::__private::DataType::Date32, $($data_type),+) => {
    252
                    $m!($crate::types::Date32Type $(, $args)*)
    253
                }
    254
                $crate::repeat_pat!($crate::cast::__private::DataType::Date64, $($data_type),+) => {
    255
                    $m!($crate::types::Date64Type $(, $args)*)
    256
                }
    257
                $crate::repeat_pat!($crate::cast::__private::DataType::Timestamp($crate::cast::__private::TimeUnit::Second, _), $($data_type),+) => {
    258
                    $m!($crate::types::TimestampSecondType $(, $args)*)
    259
                }
    260
                $crate::repeat_pat!($crate::cast::__private::DataType::Timestamp($crate::cast::__private::TimeUnit::Millisecond, _), $($data_type),+) => {
    261
                    $m!($crate::types::TimestampMillisecondType $(, $args)*)
    262
                }
    263
                $crate::repeat_pat!($crate::cast::__private::DataType::Timestamp($crate::cast::__private::TimeUnit::Microsecond, _), $($data_type),+) => {
    264
                    $m!($crate::types::TimestampMicrosecondType $(, $args)*)
    265
                }
    266
                $crate::repeat_pat!($crate::cast::__private::DataType::Timestamp($crate::cast::__private::TimeUnit::Nanosecond, _), $($data_type),+) => {
    267
                    $m!($crate::types::TimestampNanosecondType $(, $args)*)
    268
                }
    269
                $($p $(if $pred)* => $fallback,)*
    270
            }
    271
        };
    272
    }
    273
    274
    /// Downcast an [`Array`] to a temporal [`PrimitiveArray`] based on its [`DataType`]
    275
    /// accepts a number of subsequent patterns to match the data type
    276
    ///
    277
    /// ```
    278
    /// # use arrow_array::{Array, downcast_temporal_array, cast::as_string_array, cast::as_largestring_array};
    279
    /// # use arrow_schema::DataType;
    280
    ///
    281
    /// fn print_temporal(array: &dyn Array) {
    282
    ///     downcast_temporal_array!(
    283
    ///         array => {
    284
    ///             for v in array {
    285
    ///                 println!("{:?}", v);
    286
    ///             }
    287
    ///         }
    288
    ///         DataType::Utf8 => {
    289
    ///             for v in as_string_array(array) {
    290
    ///                 println!("{:?}", v);
    291
    ///             }
    292
    ///         }
    293
    ///         // You can also add a guard to the pattern
    294
    ///         DataType::LargeUtf8 if true => {
    295
    ///             for v in as_largestring_array(array) {
    296
    ///                 println!("{:?}", v);
    297
    ///             }
    298
    ///         }
    299
    ///         t => println!("Unsupported datatype {}", t)
    300
    ///     )
    301
    /// }
    302
    /// ```
    303
    ///
    304
    /// [`DataType`]: arrow_schema::DataType
    305
    #[macro_export]
    306
    macro_rules! downcast_temporal_array {
    307
        ($values:ident => $e:expr, $($p:pat $(if $pred:expr)* => $fallback:expr $(,)*)*) => {
    308
            $crate::downcast_temporal_array!($values => {$e} $($p $(if $pred)* => $fallback)*)
    309
        };
    310
        (($($values:ident),+) => $e:expr, $($p:pat $(if $pred:expr)* => $fallback:expr $(,)*)*) => {
    311
            $crate::downcast_temporal_array!($($values),+ => {$e} $($p $(if $pred)* => $fallback)*)
    312
        };
    313
        ($($values:ident),+ => $e:block $($p:pat $(if $pred:expr)* => $fallback:expr $(,)*)*) => {
    314
            $crate::downcast_temporal_array!(($($values),+) => $e $($p $(if $pred)* => $fallback)*)
    315
        };
    316
        (($($values:ident),+) => $e:block $($p:pat $(if $pred:expr)* => $fallback:expr $(,)*)*) => {
    317
            $crate::downcast_temporal!{
    318
                $($values.data_type()),+ => ($crate::downcast_primitive_array_helper, $($values),+, $e),
    319
                $($p $(if $pred)* => $fallback,)*
    320
            }
    321
        };
    322
    }
    323
    324
    /// Given one or more expressions evaluating to primitive [`DataType`] invokes the provided macro
    325
    /// `m` with the corresponding [`ArrowPrimitiveType`], followed by any additional arguments
    326
    ///
    327
    /// ```
    328
    /// # use arrow_array::{downcast_primitive, ArrowPrimitiveType};
    329
    /// # use arrow_schema::DataType;
    330
    ///
    331
    /// macro_rules! primitive_size_helper {
    332
    ///   ($t:ty, $o:ty) => {
    333
    ///       std::mem::size_of::<<$t as ArrowPrimitiveType>::Native>() as $o
    334
    ///   };
    335
    /// }
    336
    ///
    337
    /// fn primitive_size(t: &DataType) -> u8 {
    338
    ///     downcast_primitive! {
    339
    ///         t => (primitive_size_helper, u8),
    340
    ///         // You can also add a guard to the pattern
    341
    ///         DataType::LargeUtf8 if true => u8::MAX,
    342
    ///         _ => u8::MAX
    343
    ///     }
    344
    /// }
    345
    ///
    346
    /// assert_eq!(primitive_size(&DataType::Int32), 4);
    347
    /// assert_eq!(primitive_size(&DataType::Int64), 8);
    348
    /// assert_eq!(primitive_size(&DataType::Float16), 2);
    349
    /// assert_eq!(primitive_size(&DataType::Decimal128(38, 10)), 16);
    350
    /// assert_eq!(primitive_size(&DataType::Decimal256(76, 20)), 32);
    351
    /// ```
    352
    ///
    353
    /// [`DataType`]: arrow_schema::DataType
    354
    #[macro_export]
    355
    macro_rules! downcast_primitive {
    356
        ($($data_type:expr),+ => ($m:path $(, $args:tt)*), $($p:pat $(if $pred:expr)* => $fallback:expr $(,)*)*) => {
    357
            $crate::downcast_integer! {
    358
                $($data_type),+ => ($m $(, $args)*),
    359
                $crate::repeat_pat!($crate::cast::__private::DataType::Float16, $($data_type),+) => {
    360
                    $m!($crate::types::Float16Type $(, $args)*)
    361
                }
    362
                $crate::repeat_pat!($crate::cast::__private::DataType::Float32, $($data_type),+) => {
    363
                    $m!($crate::types::Float32Type $(, $args)*)
    364
                }
    365
                $crate::repeat_pat!($crate::cast::__private::DataType::Float64, $($data_type),+) => {
    366
                    $m!($crate::types::Float64Type $(, $args)*)
    367
                }
    368
                $crate::repeat_pat!($crate::cast::__private::DataType::Decimal32(_, _), $($data_type),+) => {
    369
                    $m!($crate::types::Decimal32Type $(, $args)*)
    370
                }
    371
                $crate::repeat_pat!($crate::cast::__private::DataType::Decimal64(_, _), $($data_type),+) => {
    372
                    $m!($crate::types::Decimal64Type $(, $args)*)
    373
                }
    374
                $crate::repeat_pat!($crate::cast::__private::DataType::Decimal128(_, _), $($data_type),+) => {
    375
                    $m!($crate::types::Decimal128Type $(, $args)*)
    376
                }
    377
                $crate::repeat_pat!($crate::cast::__private::DataType::Decimal256(_, _), $($data_type),+) => {
    378
                    $m!($crate::types::Decimal256Type $(, $args)*)
    379
                }
    380
                $crate::repeat_pat!($crate::cast::__private::DataType::Interval($crate::cast::__private::IntervalUnit::YearMonth), $($data_type),+) => {
    381
                    $m!($crate::types::IntervalYearMonthType $(, $args)*)
    382
                }
    383
                $crate::repeat_pat!($crate::cast::__private::DataType::Interval($crate::cast::__private::IntervalUnit::DayTime), $($data_type),+) => {
    384
                    $m!($crate::types::IntervalDayTimeType $(, $args)*)
    385
                }
    386
                $crate::repeat_pat!($crate::cast::__private::DataType::Interval($crate::cast::__private::IntervalUnit::MonthDayNano), $($data_type),+) => {
    387
                    $m!($crate::types::IntervalMonthDayNanoType $(, $args)*)
    388
                }
    389
                $crate::repeat_pat!($crate::cast::__private::DataType::Duration($crate::cast::__private::TimeUnit::Second), $($data_type),+) => {
    390
                    $m!($crate::types::DurationSecondType $(, $args)*)
    391
                }
    392
                $crate::repeat_pat!($crate::cast::__private::DataType::Duration($crate::cast::__private::TimeUnit::Millisecond), $($data_type),+) => {
    393
                    $m!($crate::types::DurationMillisecondType $(, $args)*)
    394
                }
    395
                $crate::repeat_pat!($crate::cast::__private::DataType::Duration($crate::cast::__private::TimeUnit::Microsecond), $($data_type),+) => {
    396
                    $m!($crate::types::DurationMicrosecondType $(, $args)*)
    397
                }
    398
                $crate::repeat_pat!($crate::cast::__private::DataType::Duration($crate::cast::__private::TimeUnit::Nanosecond), $($data_type),+) => {
    399
                    $m!($crate::types::DurationNanosecondType $(, $args)*)
    400
                }
    401
                _ => {
    402
                    $crate::downcast_temporal! {
    403
                        $($data_type),+ => ($m $(, $args)*),
    404
                        $($p $(if $pred)* => $fallback,)*
    405
                    }
    406
                }
    407
            }
    408
        };
    409
    }
    410
    411
    #[macro_export]
    412
    #[doc(hidden)]
    413
    macro_rules! downcast_primitive_array_helper {
    414
        ($t:ty, $($values:ident),+, $e:block) => {{
    415
            $(let $values = $crate::cast::as_primitive_array::<$t>($values);)+
    416
            $e
    417
        }};
    418
    }
    419
    420
    /// Downcast an [`Array`] to a [`PrimitiveArray`] based on its [`DataType`]
    421
    /// accepts a number of subsequent patterns to match the data type
    422
    ///
    423
    /// ```
    424
    /// # use arrow_array::{Array, downcast_primitive_array, cast::as_string_array, cast::as_largestring_array};
    425
    /// # use arrow_schema::DataType;
    426
    ///
    427
    /// fn print_primitive(array: &dyn Array) {
    428
    ///     downcast_primitive_array!(
    429
    ///         array => {
    430
    ///             for v in array {
    431
    ///                 println!("{:?}", v);
    432
    ///             }
    433
    ///         }
    434
    ///         DataType::Utf8 => {
    435
    ///             for v in as_string_array(array) {
    436
    ///                 println!("{:?}", v);
    437
    ///             }
    438
    ///         }
    439
    ///         // You can also add a guard to the pattern
    440
    ///         DataType::LargeUtf8 if true => {
    441
    ///             for v in as_largestring_array(array) {
    442
    ///                 println!("{:?}", v);
    443
    ///             }
    444
    ///         }
    445
    ///         t => println!("Unsupported datatype {}", t)
    446
    ///     )
    447
    /// }
    448
    /// ```
    449
    ///
    450
    /// [`DataType`]: arrow_schema::DataType
    451
    #[macro_export]
    452
    macro_rules! downcast_primitive_array {
    453
        ($values:ident => $e:expr, $($p:pat $(if $pred:expr)* => $fallback:expr $(,)*)*) => {
    454
            $crate::downcast_primitive_array!($values => {$e} $($p $(if $pred)* => $fallback)*)
    455
        };
    456
        (($($values:ident),+) => $e:expr, $($p:pat $(if $pred:expr)* => $fallback:expr $(,)*)*) => {
    457
            $crate::downcast_primitive_array!($($values),+ => {$e} $($p $(if $pred)* => $fallback)*)
    458
        };
    459
        ($($values:ident),+ => $e:block $($p:pat $(if $pred:expr)* => $fallback:expr $(,)*)*) => {
    460
            $crate::downcast_primitive_array!(($($values),+) => $e $($p $(if $pred)* => $fallback)*)
    461
        };
    462
        (($($values:ident),+) => $e:block $($p:pat $(if $pred:expr)* => $fallback:expr $(,)*)*) => {
    463
            $crate::downcast_primitive!{
    464
                $($values.data_type()),+ => ($crate::downcast_primitive_array_helper, $($values),+, $e),
    465
                $($p $(if $pred)* => $fallback,)*
    466
            }
    467
        };
    468
    }
    469
    470
    /// Force downcast of an [`Array`], such as an [`ArrayRef`], to
    471
    /// [`PrimitiveArray<T>`], panic'ing on failure.
    472
    ///
    473
    /// # Example
    474
    ///
    475
    /// ```
    476
    /// # use std::sync::Arc;
    477
    /// # use arrow_array::{ArrayRef, Int32Array};
    478
    /// # use arrow_array::cast::as_primitive_array;
    479
    /// # use arrow_array::types::Int32Type;
    480
    ///
    481
    /// let arr: ArrayRef = Arc::new(Int32Array::from(vec![Some(1)]));
    482
    ///
    483
    /// // Downcast an `ArrayRef` to Int32Array / PrimitiveArray<Int32>:
    484
    /// let primitive_array: &Int32Array = as_primitive_array(&arr);
    485
    ///
    486
    /// // Equivalently:
    487
    /// let primitive_array = as_primitive_array::<Int32Type>(&arr);
    488
    ///
    489
    /// // This is the equivalent of:
    490
    /// let primitive_array = arr
    491
    ///     .as_any()
    492
    ///     .downcast_ref::<Int32Array>()
    493
    ///     .unwrap();
    494
    /// ```
    495
    0
    pub fn as_primitive_array<T>(arr: &dyn Array) -> &PrimitiveArray<T>
    496
    0
    where
    497
    0
        T: ArrowPrimitiveType,
    498
    {
    499
    0
        arr.as_any()
    500
    0
            .downcast_ref::<PrimitiveArray<T>>()
    501
    0
            .expect("Unable to downcast to primitive array")
    502
    0
    }
    503
    504
    #[macro_export]
    505
    #[doc(hidden)]
    506
    macro_rules! downcast_dictionary_array_helper {
    507
        ($t:ty, $($values:ident),+, $e:block) => {{
    508
            $(let $values = $crate::cast::as_dictionary_array::<$t>($values);)+
    509
            $e
    510
        }};
    511
    }
    512
    513
    /// Downcast an [`Array`] to a [`DictionaryArray`] based on its [`DataType`], accepts
    514
    /// a number of subsequent patterns to match the data type
    515
    ///
    516
    /// ```
    517
    /// # use arrow_array::{Array, StringArray, downcast_dictionary_array, cast::as_string_array, cast::as_largestring_array};
    518
    /// # use arrow_schema::DataType;
    519
    ///
    520
    /// fn print_strings(array: &dyn Array) {
    521
    ///     downcast_dictionary_array!(
    522
    ///         array => match array.values().data_type() {
    523
    ///             DataType::Utf8 => {
    524
    ///                 for v in array.downcast_dict::<StringArray>().unwrap() {
    525
    ///                     println!("{:?}", v);
    526
    ///                 }
    527
    ///             }
    528
    ///             t => println!("Unsupported dictionary value type {}", t),
    529
    ///         },
    530
    ///         DataType::Utf8 => {
    531
    ///             for v in as_string_array(array) {
    532
    ///                 println!("{:?}", v);
    533
    ///             }
    534
    ///         }
    535
    ///         // You can also add a guard to the pattern
    536
    ///         DataType::LargeUtf8 if true => {
    537
    ///             for v in as_largestring_array(array) {
    538
    ///                 println!("{:?}", v);
    539
    ///             }
    540
    ///         }
    541
    ///         t => println!("Unsupported datatype {}", t)
    542
    ///     )
    543
    /// }
    544
    /// ```
    545
    ///
    546
    /// [`DataType`]: arrow_schema::DataType
    547
    #[macro_export]
    548
    macro_rules! downcast_dictionary_array {
    549
        ($values:ident => $e:expr, $($p:pat $(if $pred:expr)* => $fallback:expr $(,)*)*) => {
    550
            downcast_dictionary_array!($values => {$e} $($p $(if $pred)* => $fallback)*)
    551
        };
    552
    553
        ($values:ident => $e:block $($p:pat $(if $pred:expr)* => $fallback:expr $(,)*)*) => {
    554
            match $values.data_type() {
    555
                $crate::cast::__private::DataType::Dictionary(k, _) => {
    556
                    $crate::downcast_integer! {
    557
                        k.as_ref() => ($crate::downcast_dictionary_array_helper, $values, $e),
    558
                        k => unreachable!("unsupported dictionary key type: {}", k)
    559
                    }
    560
                }
    561
                $($p $(if $pred)* => $fallback,)*
    562
            }
    563
        }
    564
    }
    565
    566
    /// Force downcast of an [`Array`], such as an [`ArrayRef`] to
    567
    /// [`DictionaryArray<T>`], panic'ing on failure.
    568
    ///
    569
    /// # Example
    570
    ///
    571
    /// ```
    572
    /// # use arrow_array::{ArrayRef, DictionaryArray};
    573
    /// # use arrow_array::cast::as_dictionary_array;
    574
    /// # use arrow_array::types::Int32Type;
    575
    ///
    576
    /// let arr: DictionaryArray<Int32Type> = vec![Some("foo")].into_iter().collect();
    577
    /// let arr: ArrayRef = std::sync::Arc::new(arr);
    578
    /// let dict_array: &DictionaryArray<Int32Type> = as_dictionary_array::<Int32Type>(&arr);
    579
    /// ```
    580
    0
    pub fn as_dictionary_array<T>(arr: &dyn Array) -> &DictionaryArray<T>
    581
    0
    where
    582
    0
        T: ArrowDictionaryKeyType,
    583
    {
    584
    0
        arr.as_any()
    585
    0
            .downcast_ref::<DictionaryArray<T>>()
    586
    0
            .expect("Unable to downcast to dictionary array")
    587
    0
    }
    588
    589
    /// Force downcast of an [`Array`], such as an [`ArrayRef`] to
    590
    /// [`RunArray<T>`], panic'ing on failure.
    591
    ///
    592
    /// # Example
    593
    ///
    594
    /// ```
    595
    /// # use arrow_array::{ArrayRef, RunArray};
    596
    /// # use arrow_array::cast::as_run_array;
    597
    /// # use arrow_array::types::Int32Type;
    598
    ///
    599
    /// let arr: RunArray<Int32Type> = vec![Some("foo")].into_iter().collect();
    600
    /// let arr: ArrayRef = std::sync::Arc::new(arr);
    601
    /// let run_array: &RunArray<Int32Type> = as_run_array::<Int32Type>(&arr);
    602
    /// ```
    603
    0
    pub fn as_run_array<T>(arr: &dyn Array) -> &RunArray<T>
    604
    0
    where
    605
    0
        T: RunEndIndexType,
    606
    {
    607
    0
        arr.as_any()
    608
    0
            .downcast_ref::<RunArray<T>>()
    609
    0
            .expect("Unable to downcast to run array")
    610
    0
    }
    611
    612
    #[macro_export]
    613
    #[doc(hidden)]
    614
    macro_rules! downcast_run_array_helper {
    615
        ($t:ty, $($values:ident),+, $e:block) => {{
    616
            $(let $values = $crate::cast::as_run_array::<$t>($values);)+
    617
            $e
    618
        }};
    619
    }
    620
    621
    /// Downcast an [`Array`] to a [`RunArray`] based on its [`DataType`], accepts
    622
    /// a number of subsequent patterns to match the data type
    623
    ///
    624
    /// ```
    625
    /// # use arrow_array::{Array, StringArray, downcast_run_array, cast::as_string_array, cast::as_largestring_array};
    626
    /// # use arrow_schema::DataType;
    627
    ///
    628
    /// fn print_strings(array: &dyn Array) {
    629
    ///     downcast_run_array!(
    630
    ///         array => match array.values().data_type() {
    631
    ///             DataType::Utf8 => {
    632
    ///                 for v in array.downcast::<StringArray>().unwrap() {
    633
    ///                     println!("{:?}", v);
    634
    ///                 }
    635
    ///             }
    636
    ///             t => println!("Unsupported run array value type {}", t),
    637
    ///         },
    638
    ///         DataType::Utf8 => {
    639
    ///             for v in as_string_array(array) {
    640
    ///                 println!("{:?}", v);
    641
    ///             }
    642
    ///         }
    643
    ///         // You can also add a guard to the pattern
    644
    ///         DataType::LargeUtf8 if true => {
    645
    ///             for v in as_largestring_array(array) {
    646
    ///                 println!("{:?}", v);
    647
    ///             }
    648
    ///         }
    649
    ///         t => println!("Unsupported datatype {}", t)
    650
    ///     )
    651
    /// }
    652
    /// ```
    653
    ///
    654
    /// [`DataType`]: arrow_schema::DataType
    655
    #[macro_export]
    656
    macro_rules! downcast_run_array {
    657
        ($values:ident => $e:expr, $($p:pat $(if $pred:expr)* => $fallback:expr $(,)*)*) => {
    658
            downcast_run_array!($values => {$e} $($p $(if $pred)* => $fallback)*)
    659
        };
    660
    661
        ($values:ident => $e:block $($p:pat $(if $pred:expr)* => $fallback:expr $(,)*)*) => {
    662
            match $values.data_type() {
    663
                $crate::cast::__private::DataType::RunEndEncoded(k, _) => {
    664
                    $crate::downcast_run_end_index! {
    665
                        k.data_type() => ($crate::downcast_run_array_helper, $values, $e),
    666
                        k => unreachable!("unsupported run end index type: {}", k)
    667
                    }
    668
                }
    669
                $($p $(if $pred)* => $fallback,)*
    670
            }
    671
        }
    672
    }
    673
    674
    /// Force downcast of an [`Array`], such as an [`ArrayRef`] to
    675
    /// [`GenericListArray<T>`], panicking on failure.
    676
    0
    pub fn as_generic_list_array<S: OffsetSizeTrait>(arr: &dyn Array) -> &GenericListArray<S> {
    677
    0
        arr.as_any()
    678
    0
            .downcast_ref::<GenericListArray<S>>()
    679
    0
            .expect("Unable to downcast to list array")
    680
    0
    }
    681
    682
    /// Force downcast of an [`Array`], such as an [`ArrayRef`] to
    683
    /// [`ListArray`], panicking on failure.
    684
    #[inline]
    685
    0
    pub fn as_list_array(arr: &dyn Array) -> &ListArray {
    686
    0
        as_generic_list_array::<i32>(arr)
    687
    0
    }
    688
    689
    /// Force downcast of an [`Array`], such as an [`ArrayRef`] to
    690
    /// [`FixedSizeListArray`], panicking on failure.
    691
    #[inline]
    692
    0
    pub fn as_fixed_size_list_array(arr: &dyn Array) -> &FixedSizeListArray {
    693
    0
        arr.as_any()
    694
    0
            .downcast_ref::<FixedSizeListArray>()
    695
    0
            .expect("Unable to downcast to fixed size list array")
    696
    0
    }
    697
    698
    /// Force downcast of an [`Array`], such as an [`ArrayRef`] to
    699
    /// [`LargeListArray`], panicking on failure.
    700
    #[inline]
    701
    0
    pub fn as_large_list_array(arr: &dyn Array) -> &LargeListArray {
    702
    0
        as_generic_list_array::<i64>(arr)
    703
    0
    }
    704
    705
    /// Force downcast of an [`Array`], such as an [`ArrayRef`] to
    706
    /// [`GenericBinaryArray<S>`], panicking on failure.
    707
    #[inline]
    708
    0
    pub fn as_generic_binary_array<S: OffsetSizeTrait>(arr: &dyn Array) -> &GenericBinaryArray<S> {
    709
    0
        arr.as_any()
    710
    0
            .downcast_ref::<GenericBinaryArray<S>>()
    711
    0
            .expect("Unable to downcast to binary array")
    712
    0
    }
    713
    714
    /// Force downcast of an [`Array`], such as an [`ArrayRef`] to
    715
    /// [`StringArray`], panicking on failure.
    716
    ///
    717
    /// # Example
    718
    ///
    719
    /// ```
    720
    /// # use std::sync::Arc;
    721
    /// # use arrow_array::cast::as_string_array;
    722
    /// # use arrow_array::{ArrayRef, StringArray};
    723
    ///
    724
    /// let arr: ArrayRef = Arc::new(StringArray::from_iter(vec![Some("foo")]));
    725
    /// let string_array = as_string_array(&arr);
    726
    /// ```
    727
    0
    pub fn as_string_array(arr: &dyn Array) -> &StringArray {
    728
    0
        arr.as_any()
    729
    0
            .downcast_ref::<StringArray>()
    730
    0
            .expect("Unable to downcast to StringArray")
    731
    0
    }
    732
    733
    /// Force downcast of an [`Array`], such as an [`ArrayRef`] to
    734
    /// [`BooleanArray`], panicking on failure.
    735
    ///
    736
    /// # Example
    737
    ///
    738
    /// ```
    739
    /// # use std::sync::Arc;
    740
    /// # use arrow_array::{ArrayRef, BooleanArray};
    741
    /// # use arrow_array::cast::as_boolean_array;
    742
    ///
    743
    /// let arr: ArrayRef = Arc::new(BooleanArray::from_iter(vec![Some(true)]));
    744
    /// let boolean_array = as_boolean_array(&arr);
    745
    /// ```
    746
    0
    pub fn as_boolean_array(arr: &dyn Array) -> &BooleanArray {
    747
    0
        arr.as_any()
    748
    0
            .downcast_ref::<BooleanArray>()
    749
    0
            .expect("Unable to downcast to BooleanArray")
    750
    0
    }
    751
    752
    macro_rules! array_downcast_fn {
    753
        ($name: ident, $arrty: ty, $arrty_str:expr) => {
    754
            #[doc = "Force downcast of an [`Array`], such as an [`ArrayRef`] to "]
    755
            #[doc = $arrty_str]
    756
    0
            pub fn $name(arr: &dyn Array) -> &$arrty {
    757
    0
                arr.as_any().downcast_ref::<$arrty>().expect(concat!(
    758
    0
                    "Unable to downcast to typed array through ",
    759
    0
                    stringify!($name)
    760
    0
                ))
    761
    0
            }
    762
        };
    763
    764
        // use recursive macro to generate dynamic doc string for a given array type
    765
        ($name: ident, $arrty: ty) => {
    766
            array_downcast_fn!(
    767
                $name,
    768
                $arrty,
    769
                concat!("[`", stringify!($arrty), "`], panicking on failure.")
    770
            );
    771
        };
    772
    }
    773
    774
    array_downcast_fn!(as_largestring_array, LargeStringArray);
    775
    array_downcast_fn!(as_null_array, NullArray);
    776
    array_downcast_fn!(as_struct_array, StructArray);
    777
    array_downcast_fn!(as_union_array, UnionArray);
    778
    array_downcast_fn!(as_map_array, MapArray);
    779
    780
    /// Downcasts a `dyn Array` to a concrete type
    781
    ///
    782
    /// ```
    783
    /// # use arrow_array::{BooleanArray, Int32Array, RecordBatch, StringArray};
    784
    /// # use arrow_array::cast::downcast_array;
    785
    /// struct ConcreteBatch {
    786
    ///     col1: Int32Array,
    787
    ///     col2: BooleanArray,
    788
    ///     col3: StringArray,
    789
    /// }
    790
    ///
    791
    /// impl ConcreteBatch {
    792
    ///     fn new(batch: &RecordBatch) -> Self {
    793
    ///         Self {
    794
    ///             col1: downcast_array(batch.column(0).as_ref()),
    795
    ///             col2: downcast_array(batch.column(1).as_ref()),
    796
    ///             col3: downcast_array(batch.column(2).as_ref()),
    797
    ///         }
    798
    ///     }
    799
    /// }
    800
    /// ```
    801
    ///
    802
    /// # Panics
    803
    ///
    804
    /// Panics if array is not of the correct data type
    805
    pub fn downcast_array<T>(array: &dyn Array) -> T
    806
    where
    807
        T: From<ArrayData>,
    808
    {
    809
        T::from(array.to_data())
    810
    }
    811
    812
    mod private {
    813
        pub trait Sealed {}
    814
    }
    815
    816
    /// An extension trait for `dyn Array` that provides ergonomic downcasting
    817
    ///
    818
    /// ```
    819
    /// # use std::sync::Arc;
    820
    /// # use arrow_array::{ArrayRef, Int32Array};
    821
    /// # use arrow_array::cast::AsArray;
    822
    /// # use arrow_array::types::Int32Type;
    823
    /// let col = Arc::new(Int32Array::from(vec![1, 2, 3])) as ArrayRef;
    824
    /// assert_eq!(col.as_primitive::<Int32Type>().values(), &[1, 2, 3]);
    825
    /// ```
    826
    pub trait AsArray: private::Sealed {
    827
        /// Downcast this to a [`BooleanArray`] returning `None` if not possible
    828
        fn as_boolean_opt(&self) -> Option<&BooleanArray>;
    829
    830
        /// Downcast this to a [`BooleanArray`] panicking if not possible
    831
    20
        fn as_boolean(&self) -> &BooleanArray {
    832
    20
            self.as_boolean_opt().expect("boolean array")
    833
    20
        }
    834
    835
        /// Downcast this to a [`PrimitiveArray`] returning `None` if not possible
    836
        fn as_primitive_opt<T: ArrowPrimitiveType>(&self) -> Option<&PrimitiveArray<T>>;
    837
    838
        /// Downcast this to a [`PrimitiveArray`] panicking if not possible
    839
    233
        fn as_primitive<T: ArrowPrimitiveType>(&self) -> &PrimitiveArray<T> {
    840
    233
            self.as_primitive_opt().expect("primitive array")
    841
    233
        }
    842
    843
        /// Downcast this to a [`GenericByteArray`] returning `None` if not possible
    844
        fn as_bytes_opt<T: ByteArrayType>(&self) -> Option<&GenericByteArray<T>>;
    845
    846
        /// Downcast this to a [`GenericByteArray`] panicking if not possible
    847
    74
        fn as_bytes<T: ByteArrayType>(&self) -> &GenericByteArray<T> {
    848
    74
            self.as_bytes_opt().expect("byte array")
    849
    74
        }
    850
    851
        /// Downcast this to a [`GenericStringArray`] returning `None` if not possible
    852
        fn as_string_opt<O: OffsetSizeTrait>(&self) -> Option<&GenericStringArray<O>> {
    853
            self.as_bytes_opt()
    854
        }
    855
    856
        /// Downcast this to a [`GenericStringArray`] panicking if not possible
    857
    6
        fn as_string<O: OffsetSizeTrait>(&self) -> &GenericStringArray<O> {
    858
    6
            self.as_bytes_opt().expect("string array")
    859
    6
        }
    860
    861
        /// Downcast this to a [`GenericBinaryArray`] returning `None` if not possible
    862
        fn as_binary_opt<O: OffsetSizeTrait>(&self) -> Option<&GenericBinaryArray<O>> {
    863
            self.as_bytes_opt()
    864
        }
    865
    866
        /// Downcast this to a [`GenericBinaryArray`] panicking if not possible
    867
    13
        fn as_binary<O: OffsetSizeTrait>(&self) -> &GenericBinaryArray<O> {
    868
    13
            self.as_bytes_opt().expect("binary array")
    869
    13
        }
    870
    871
        /// Downcast this to a [`StringViewArray`] returning `None` if not possible
    872
        fn as_string_view_opt(&self) -> Option<&StringViewArray> {
    873
            self.as_byte_view_opt()
    874
        }
    875
    876
        /// Downcast this to a [`StringViewArray`] panicking if not possible
    877
    0
        fn as_string_view(&self) -> &StringViewArray {
    878
    0
            self.as_byte_view_opt().expect("string view array")
    879
    0
        }
    880
    881
        /// Downcast this to a [`BinaryViewArray`] returning `None` if not possible
    882
        fn as_binary_view_opt(&self) -> Option<&BinaryViewArray> {
    883
            self.as_byte_view_opt()
    884
        }
    885
    886
        /// Downcast this to a [`BinaryViewArray`] panicking if not possible
    887
    0
        fn as_binary_view(&self) -> &BinaryViewArray {
    888
    0
            self.as_byte_view_opt().expect("binary view array")
    889
    0
        }
    890
    891
        /// Downcast this to a [`GenericByteViewArray`] returning `None` if not possible
    892
        fn as_byte_view_opt<T: ByteViewType>(&self) -> Option<&GenericByteViewArray<T>>;
    893
    894
        /// Downcast this to a [`GenericByteViewArray`] panicking if not possible
    895
    0
        fn as_byte_view<T: ByteViewType>(&self) -> &GenericByteViewArray<T> {
    896
    0
            self.as_byte_view_opt().expect("byte view array")
    897
    0
        }
    898
    899
        /// Downcast this to a [`StructArray`] returning `None` if not possible
    900
        fn as_struct_opt(&self) -> Option<&StructArray>;
    901
    902
        /// Downcast this to a [`StructArray`] panicking if not possible
    903
    13
        fn as_struct(&self) -> &StructArray {
    904
    13
            self.as_struct_opt().expect("struct array")
    905
    13
        }
    906
    907
        /// Downcast this to a [`UnionArray`] returning `None` if not possible
    908
        fn as_union_opt(&self) -> Option<&UnionArray>;
    909
    910
        /// Downcast this to a [`UnionArray`] panicking if not possible
    911
    0
        fn as_union(&self) -> &UnionArray {
    912
    0
            self.as_union_opt().expect("union array")
    913
    0
        }
    914
    915
        /// Downcast this to a [`GenericListArray`] returning `None` if not possible
    916
        fn as_list_opt<O: OffsetSizeTrait>(&self) -> Option<&GenericListArray<O>>;
    917
    918
        /// Downcast this to a [`GenericListArray`] panicking if not possible
    919
    23
        fn as_list<O: OffsetSizeTrait>(&self) -> &GenericListArray<O> {
    920
    23
            self.as_list_opt().expect("list array")
    921
    23
        }
    922
    923
        /// Downcast this to a [`GenericListViewArray`] returning `None` if not possible
    924
        fn as_list_view_opt<O: OffsetSizeTrait>(&self) -> Option<&GenericListViewArray<O>>;
    925
    926
        /// Downcast this to a [`GenericListViewArray`] panicking if not possible
    927
        fn as_list_view<O: OffsetSizeTrait>(&self) -> &GenericListViewArray<O> {
    928
            self.as_list_view_opt().expect("list view array")
    929
        }
    930
    931
        /// Downcast this to a [`FixedSizeBinaryArray`] returning `None` if not possible
    932
        fn as_fixed_size_binary_opt(&self) -> Option<&FixedSizeBinaryArray>;
    933
    934
        /// Downcast this to a [`FixedSizeBinaryArray`] panicking if not possible
    935
    0
        fn as_fixed_size_binary(&self) -> &FixedSizeBinaryArray {
    936
    0
            self.as_fixed_size_binary_opt()
    937
    0
                .expect("fixed size binary array")
    938
    0
        }
    939
    940
        /// Downcast this to a [`FixedSizeListArray`] returning `None` if not possible
    941
        fn as_fixed_size_list_opt(&self) -> Option<&FixedSizeListArray>;
    942
    943
        /// Downcast this to a [`FixedSizeListArray`] panicking if not possible
    944
    0
        fn as_fixed_size_list(&self) -> &FixedSizeListArray {
    945
    0
            self.as_fixed_size_list_opt()
    946
    0
                .expect("fixed size list array")
    947
    0
        }
    948
    949
        /// Downcast this to a [`MapArray`] returning `None` if not possible
    950
        fn as_map_opt(&self) -> Option<&MapArray>;
    951
    952
        /// Downcast this to a [`MapArray`] panicking if not possible
    953
    0
        fn as_map(&self) -> &MapArray {
    954
    0
            self.as_map_opt().expect("map array")
    955
    0
        }
    956
    957
        /// Downcast this to a [`DictionaryArray`] returning `None` if not possible
    958
        fn as_dictionary_opt<K: ArrowDictionaryKeyType>(&self) -> Option<&DictionaryArray<K>>;
    959
    960
        /// Downcast this to a [`DictionaryArray`] panicking if not possible
    961
    6
        fn as_dictionary<K: ArrowDictionaryKeyType>(&self) -> &DictionaryArray<K> {
    962
    6
            self.as_dictionary_opt().expect("dictionary array")
    963
    6
        }
    964
    965
        /// Downcast this to a [`RunArray`] returning `None` if not possible
    966
        fn as_run_opt<K: RunEndIndexType>(&self) -> Option<&RunArray<K>>;
    967
    968
        /// Downcast this to a [`RunArray`] panicking if not possible
    969
    0
        fn as_run<K: RunEndIndexType>(&self) -> &RunArray<K> {
    970
    0
            self.as_run_opt().expect("run array")
    971
    0
        }
    972
    973
        /// Downcasts this to a [`AnyDictionaryArray`] returning `None` if not possible
    974
        fn as_any_dictionary_opt(&self) -> Option<&dyn AnyDictionaryArray>;
    975
    976
        /// Downcasts this to a [`AnyDictionaryArray`] panicking if not possible
    977
    0
        fn as_any_dictionary(&self) -> &dyn AnyDictionaryArray {
    978
    0
            self.as_any_dictionary_opt().expect("any dictionary array")
    979
    0
        }
    980
    }
    981
    982
    impl private::Sealed for dyn Array + '_ {}
    983
    impl AsArray for dyn Array + '_ {
    984
    20
        fn as_boolean_opt(&self) -> Option<&BooleanArray> {
    985
    20
            self.as_any().downcast_ref()
    986
    20
        }
    987
    988
    233
        fn as_primitive_opt<T: ArrowPrimitiveType>(&self) -> Option<&PrimitiveArray<T>> {
    989
    233
            self.as_any().downcast_ref()
    990
    233
        }
    991
    992
    99
        fn as_bytes_opt<T: ByteArrayType>(&self) -> Option<&GenericByteArray<T>> {
    993
    99
            self.as_any().downcast_ref()
    994
    99
        }
    995
    996
    0
        fn as_byte_view_opt<T: ByteViewType>(&self) -> Option<&GenericByteViewArray<T>> {
    997
    0
            self.as_any().downcast_ref()
    998
    0
        }
    999
    1000
    13
        fn as_struct_opt(&self) -> Option<&StructArray> {
    1001
    13
            self.as_any().downcast_ref()
    1002
    13
        }
    1003
    1004
    0
        fn as_union_opt(&self) -> Option<&UnionArray> {
    1005
    0
            self.as_any().downcast_ref()
    1006
    0
        }
    1007
    1008
    23
        fn as_list_opt<O: OffsetSizeTrait>(&self) -> Option<&GenericListArray<O>> {
    1009
    23
            self.as_any().downcast_ref()
    1010
    23
        }
    1011
    1012
        fn as_list_view_opt<O: OffsetSizeTrait>(&self) -> Option<&GenericListViewArray<O>> {
    1013
            self.as_any().downcast_ref()
    1014
        }
    1015
    1016
    0
        fn as_fixed_size_binary_opt(&self) -> Option<&FixedSizeBinaryArray> {
    1017
    0
            self.as_any().downcast_ref()
    1018
    0
        }
    1019
    1020
    0
        fn as_fixed_size_list_opt(&self) -> Option<&FixedSizeListArray> {
    1021
    0
            self.as_any().downcast_ref()
    1022
    0
        }
    1023
    1024
    0
        fn as_map_opt(&self) -> Option<&MapArray> {
    1025
    0
            self.as_any().downcast_ref()
    1026
    0
        }
    1027
    1028
    6
        fn as_dictionary_opt<K: ArrowDictionaryKeyType>(&self) -> Option<&DictionaryArray<K>> {
    1029
    6
            self.as_any().downcast_ref()
    1030
    6
        }
    1031
    1032
    0
        fn as_run_opt<K: RunEndIndexType>(&self) -> Option<&RunArray<K>> {
    1033
    0
            self.as_any().downcast_ref()
    1034
    0
        }
    1035
    1036
    0
        fn as_any_dictionary_opt(&self) -> Option<&dyn AnyDictionaryArray> {
    1037
    0
            let array = self;
    1038
    0
            downcast_dictionary_array! {
    1039
    0
                array => Some(array),
    1040
    0
                _ => None
    1041
            }
    1042
    0
        }
    1043
    }
    1044
    1045
    impl private::Sealed for ArrayRef {}
    1046
    impl AsArray for ArrayRef {
    1047
    0
        fn as_boolean_opt(&self) -> Option<&BooleanArray> {
    1048
    0
            self.as_ref().as_boolean_opt()
    1049
    0
        }
    1050
    1051
    2
        fn as_primitive_opt<T: ArrowPrimitiveType>(&self) -> Option<&PrimitiveArray<T>> {
    1052
    2
            self.as_ref().as_primitive_opt()
    1053
    2
        }
    1054
    1055
    0
        fn as_bytes_opt<T: ByteArrayType>(&self) -> Option<&GenericByteArray<T>> {
    1056
    0
            self.as_ref().as_bytes_opt()
    1057
    0
        }
    1058
    1059
    0
        fn as_byte_view_opt<T: ByteViewType>(&self) -> Option<&GenericByteViewArray<T>> {
    1060
    0
            self.as_ref().as_byte_view_opt()
    1061
    0
        }
    1062
    1063
    0
        fn as_struct_opt(&self) -> Option<&StructArray> {
    1064
    0
            self.as_ref().as_struct_opt()
    1065
    0
        }
    1066
    1067
    0
        fn as_union_opt(&self) -> Option<&UnionArray> {
    1068
    0
            self.as_any().downcast_ref()
    1069
    0
        }
    1070
    1071
        fn as_list_opt<O: OffsetSizeTrait>(&self) -> Option<&GenericListArray<O>> {
    1072
            self.as_ref().as_list_opt()
    1073
        }
    1074
    1075
        fn as_list_view_opt<O: OffsetSizeTrait>(&self) -> Option<&GenericListViewArray<O>> {
    1076
            self.as_ref().as_list_view_opt()
    1077
        }
    1078
    1079
    0
        fn as_fixed_size_binary_opt(&self) -> Option<&FixedSizeBinaryArray> {
    1080
    0
            self.as_ref().as_fixed_size_binary_opt()
    1081
    0
        }
    1082
    1083
    0
        fn as_fixed_size_list_opt(&self) -> Option<&FixedSizeListArray> {
    1084
    0
            self.as_ref().as_fixed_size_list_opt()
    1085
    0
        }
    1086
    1087
    0
        fn as_map_opt(&self) -> Option<&MapArray> {
    1088
    0
            self.as_any().downcast_ref()
    1089
    0
        }
    1090
    1091
    0
        fn as_dictionary_opt<K: ArrowDictionaryKeyType>(&self) -> Option<&DictionaryArray<K>> {
    1092
    0
            self.as_ref().as_dictionary_opt()
    1093
    0
        }
    1094
    1095
    0
        fn as_any_dictionary_opt(&self) -> Option<&dyn AnyDictionaryArray> {
    1096
    0
            self.as_ref().as_any_dictionary_opt()
    1097
    0
        }
    1098
    1099
    0
        fn as_run_opt<K: RunEndIndexType>(&self) -> Option<&RunArray<K>> {
    1100
    0
            self.as_ref().as_run_opt()
    1101
    0
        }
    1102
    1103
        fn as_string_opt<O: OffsetSizeTrait>(&self) -> Option<&GenericStringArray<O>> {
    1104
            self.as_ref().as_string_opt()
    1105
        }
    1106
    }
    1107
    1108
    #[cfg(test)]
    1109
    mod tests {
    1110
        use super::*;
    1111
        use arrow_buffer::i256;
    1112
        use arrow_schema::DataType;
    1113
        use std::sync::Arc;
    1114
    1115
        #[test]
    1116
        fn test_as_primitive_array_ref() {
    1117
            let array: Int32Array = vec![1, 2, 3].into_iter().map(Some).collect();
    1118
            assert!(!as_primitive_array::<Int32Type>(&array).is_empty());
    1119
    1120
            // should also work when wrapped in an Arc
    1121
            let array: ArrayRef = Arc::new(array);
    1122
            assert!(!as_primitive_array::<Int32Type>(&array).is_empty());
    1123
        }
    1124
    1125
        #[test]
    1126
        fn test_as_string_array_ref() {
    1127
            let array: StringArray = vec!["foo", "bar"].into_iter().map(Some).collect();
    1128
            assert!(!as_string_array(&array).is_empty());
    1129
    1130
            // should also work when wrapped in an Arc
    1131
            let array: ArrayRef = Arc::new(array);
    1132
            assert!(!as_string_array(&array).is_empty())
    1133
        }
    1134
    1135
        #[test]
    1136
        fn test_decimal32array() {
    1137
            let a = Decimal32Array::from_iter_values([1, 2, 4, 5]);
    1138
            assert!(!as_primitive_array::<Decimal32Type>(&a).is_empty());
    1139
        }
    1140
    1141
        #[test]
    1142
        fn test_decimal64array() {
    1143
            let a = Decimal64Array::from_iter_values([1, 2, 4, 5]);
    1144
            assert!(!as_primitive_array::<Decimal64Type>(&a).is_empty());
    1145
        }
    1146
    1147
        #[test]
    1148
        fn test_decimal128array() {
    1149
            let a = Decimal128Array::from_iter_values([1, 2, 4, 5]);
    1150
            assert!(!as_primitive_array::<Decimal128Type>(&a).is_empty());
    1151
        }
    1152
    1153
        #[test]
    1154
        fn test_decimal256array() {
    1155
            let a = Decimal256Array::from_iter_values([1, 2, 4, 5].into_iter().map(i256::from_i128));
    1156
            assert!(!as_primitive_array::<Decimal256Type>(&a).is_empty());
    1157
        }
    1158
    1159
        #[test]
    1160
        fn downcast_integer_array_should_match_only_integers() {
    1161
            let i32_array: ArrayRef = Arc::new(Int32Array::new_null(1));
    1162
            let i32_array_ref = &i32_array;
    1163
            downcast_integer_array!(
    1164
                i32_array_ref => {
    1165
                    assert_eq!(i32_array_ref.null_count(), 1);
    1166
                },
    1167
                _ => panic!("unexpected data type")
    1168
            );
    1169
        }
    1170
    1171
        #[test]
    1172
        fn downcast_integer_array_should_not_match_primitive_that_are_not_integers() {
    1173
            let array: ArrayRef = Arc::new(Float32Array::new_null(1));
    1174
            let array_ref = &array;
    1175
            downcast_integer_array!(
    1176
                array_ref => {
    1177
                    panic!("unexpected data type {}", array_ref.data_type())
    1178
                },
    1179
                DataType::Float32 => {
    1180
                    assert_eq!(array_ref.null_count(), 1);
    1181
                },
    1182
                _ => panic!("unexpected data type")
    1183
            );
    1184
        }
    1185
    1186
        #[test]
    1187
        fn downcast_integer_array_should_not_match_non_primitive() {
    1188
            let array: ArrayRef = Arc::new(StringArray::new_null(1));
    1189
            let array_ref = &array;
    1190
            downcast_integer_array!(
    1191
                array_ref => {
    1192
                    panic!("unexpected data type {}", array_ref.data_type())
    1193
                },
    1194
                DataType::Utf8 => {
    1195
                    assert_eq!(array_ref.null_count(), 1);
    1196
                },
    1197
                _ => panic!("unexpected data type")
    1198
            );
    1199
        }
    1200
    }