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
}