You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@arrow.apache.org by tu...@apache.org on 2022/10/18 02:49:07 UTC

[arrow-rs] branch master updated: Add downcast_integer and downcast_primitive (#2872)

This is an automated email from the ASF dual-hosted git repository.

tustvold pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/arrow-rs.git


The following commit(s) were added to refs/heads/master by this push:
     new 02cab5443 Add downcast_integer and downcast_primitive (#2872)
02cab5443 is described below

commit 02cab5443c0703ce5fa86647b834f184bba172ba
Author: Raphael Taylor-Davies <17...@users.noreply.github.com>
AuthorDate: Tue Oct 18 15:49:01 2022 +1300

    Add downcast_integer and downcast_primitive (#2872)
    
    * Add downcast_integer and downcast_primitive
    
    * Fix doc
    
    * Review feedback
---
 arrow-array/src/cast.rs     | 408 ++++++++++++++++++++------------------------
 arrow/src/row/dictionary.rs |  67 +-------
 arrow/src/row/mod.rs        |  81 +--------
 3 files changed, 204 insertions(+), 352 deletions(-)

diff --git a/arrow-array/src/cast.rs b/arrow-array/src/cast.rs
index 6eb540796..e4e290501 100644
--- a/arrow-array/src/cast.rs
+++ b/arrow-array/src/cast.rs
@@ -24,221 +24,221 @@ use crate::types::*;
 #[doc(hidden)]
 #[macro_export]
 macro_rules! repeat_pat {
-    ($e:pat, $v_:ident) => {
+    ($e:pat, $v_:expr) => {
         $e
     };
-    ($e:pat, $v_:ident $(, $tail:ident)+) => {
+    ($e:pat, $v_:expr $(, $tail:expr)+) => {
         ($e, $crate::repeat_pat!($e $(, $tail)+))
     }
 }
 
-/// Downcast an [`Array`] to a [`PrimitiveArray`] based on its [`DataType`]
-/// accepts a number of subsequent patterns to match the data type
+/// Given one or more expressions evaluating to an integer [`DataType`] invokes the provided macro
+/// `m` with the corresponding integer [`ArrowPrimitiveType`], followed by any additional arguments
 ///
 /// ```
-/// # use arrow_array::{Array, downcast_primitive_array, cast::as_string_array};
+/// # use arrow_array::{downcast_primitive, ArrowPrimitiveType, downcast_integer};
 /// # use arrow_schema::DataType;
 ///
-/// fn print_primitive(array: &dyn Array) {
-///     downcast_primitive_array!(
-///         array => {
-///             for v in array {
-///                 println!("{:?}", v);
-///             }
-///         }
-///         DataType::Utf8 => {
-///             for v in as_string_array(array) {
-///                 println!("{:?}", v);
-///             }
-///         }
-///         t => println!("Unsupported datatype {}", t)
-///     )
+/// macro_rules! dictionary_key_size_helper {
+///   ($t:ty, $o:ty) => {
+///       std::mem::size_of::<<$t as ArrowPrimitiveType>::Native>() as $o
+///   };
+/// }
+///
+/// fn dictionary_key_size(t: &DataType) -> u8 {
+///     match t {
+///         DataType::Dictionary(k, _) => downcast_integer! {
+///             k.as_ref() => (dictionary_key_size_helper, u8),
+///             _ => unreachable!(),
+///         },
+///         _ => u8::MAX,
+///     }
 /// }
+///
+/// assert_eq!(dictionary_key_size(&DataType::Dictionary(Box::new(DataType::Int32), Box::new(DataType::Utf8))), 4);
+/// assert_eq!(dictionary_key_size(&DataType::Dictionary(Box::new(DataType::Int64), Box::new(DataType::Utf8))), 8);
+/// assert_eq!(dictionary_key_size(&DataType::Dictionary(Box::new(DataType::UInt16), Box::new(DataType::Utf8))), 2);
 /// ```
 ///
 /// [`DataType`]: arrow_schema::DataType
 #[macro_export]
-macro_rules! downcast_primitive_array {
-    ($values:ident => $e:expr, $($p:pat => $fallback:expr $(,)*)*) => {
-        downcast_primitive_array!($values => {$e} $($p => $fallback)*)
-    };
-    (($($values:ident),+) => $e:block $($($p:pat),+ => $fallback:expr $(,)*)*) => {
-        $crate::downcast_primitive_array!($($values),+ => $e $($($p),+ => $fallback)*)
-    };
-    (($($values:ident),+) => $e:block $(($($p:pat),+) => $fallback:expr $(,)*)*) => {
-        $crate::downcast_primitive_array!($($values),+ => $e $($($p),+ => $fallback)*)
-    };
-    ($($values:ident),+ => $e:block $($($p:pat),+ => $fallback:expr $(,)*)*) => {
-        match ($($values.data_type()),+) {
-            $crate::repeat_pat!(arrow_schema::DataType::Int8, $($values),+) => {
-                $(let $values = $crate::cast::as_primitive_array::<
-                    $crate::types::Int8Type,
-                >($values);)+
-                $e
+macro_rules! downcast_integer {
+    ($($data_type:expr),+ => ($m:path $(, $args:tt)*), $($($p:pat),+ => $fallback:expr $(,)*)*) => {
+        match ($($data_type),+) {
+            $crate::repeat_pat!(arrow_schema::DataType::Int8, $($data_type),+) => {
+                $m!($crate::types::Int8Type $(, $args)*)
             }
-            $crate::repeat_pat!(arrow_schema::DataType::Int16, $($values),+) => {
-                $(let $values = $crate::cast::as_primitive_array::<
-                    $crate::types::Int16Type,
-                >($values);)+
-                $e
+            $crate::repeat_pat!(arrow_schema::DataType::Int16, $($data_type),+) => {
+                $m!($crate::types::Int16Type $(, $args)*)
             }
-            $crate::repeat_pat!(arrow_schema::DataType::Int32, $($values),+) => {
-                $(let $values = $crate::cast::as_primitive_array::<
-                    $crate::types::Int32Type,
-                >($values);)+
-                $e
+            $crate::repeat_pat!(arrow_schema::DataType::Int32, $($data_type),+) => {
+                $m!($crate::types::Int32Type $(, $args)*)
             }
-            $crate::repeat_pat!(arrow_schema::DataType::Int64, $($values),+) => {
-                $(let $values = $crate::cast::as_primitive_array::<
-                    $crate::types::Int64Type,
-                >($values);)+
-                $e
+            $crate::repeat_pat!(arrow_schema::DataType::Int64, $($data_type),+) => {
+                $m!($crate::types::Int64Type $(, $args)*)
             }
-            $crate::repeat_pat!(arrow_schema::DataType::UInt8, $($values),+) => {
-                $(let $values = $crate::cast::as_primitive_array::<
-                    $crate::types::UInt8Type,
-                >($values);)+
-                $e
+            $crate::repeat_pat!(arrow_schema::DataType::UInt8, $($data_type),+) => {
+                $m!($crate::types::UInt8Type $(, $args)*)
             }
-            $crate::repeat_pat!(arrow_schema::DataType::UInt16, $($values),+) => {
-                $(let $values = $crate::cast::as_primitive_array::<
-                    $crate::types::UInt16Type,
-                >($values);)+
-                $e
+            $crate::repeat_pat!(arrow_schema::DataType::UInt16, $($data_type),+) => {
+                $m!($crate::types::UInt16Type $(, $args)*)
             }
-            $crate::repeat_pat!(arrow_schema::DataType::UInt32, $($values),+) => {
-                $(let $values = $crate::cast::as_primitive_array::<
-                    $crate::types::UInt32Type,
-                >($values);)+
-                $e
+            $crate::repeat_pat!(arrow_schema::DataType::UInt32, $($data_type),+) => {
+                $m!($crate::types::UInt32Type $(, $args)*)
             }
-            $crate::repeat_pat!(arrow_schema::DataType::UInt64, $($values),+) => {
-                $(let $values = $crate::cast::as_primitive_array::<
-                    $crate::types::UInt64Type,
-                >($values);)+
-                $e
+            $crate::repeat_pat!(arrow_schema::DataType::UInt64, $($data_type),+) => {
+                $m!($crate::types::UInt64Type $(, $args)*)
             }
-            $crate::repeat_pat!(arrow_schema::DataType::Float16, $($values),+) => {
-                $(let $values = $crate::cast::as_primitive_array::<
-                    $crate::types::Float16Type,
-                >($values);)+
-                $e
+            $(($($p),+) => $fallback,)*
+        }
+    };
+}
+
+/// Given one or more expressions evaluating to primitive [`DataType`] invokes the provided macro
+/// `m` with the corresponding [`ArrowPrimitiveType`], followed by any additional arguments
+///
+/// ```
+/// # use arrow_array::{downcast_primitive, ArrowPrimitiveType};
+/// # use arrow_schema::DataType;
+///
+/// macro_rules! primitive_size_helper {
+///   ($t:ty, $o:ty) => {
+///       std::mem::size_of::<<$t as ArrowPrimitiveType>::Native>() as $o
+///   };
+/// }
+///
+/// fn primitive_size(t: &DataType) -> u8 {
+///     downcast_primitive! {
+///         t => (primitive_size_helper, u8),
+///         _ => u8::MAX
+///     }
+/// }
+///
+/// assert_eq!(primitive_size(&DataType::Int32), 4);
+/// assert_eq!(primitive_size(&DataType::Int64), 8);
+/// assert_eq!(primitive_size(&DataType::Float16), 2);
+/// ```
+///
+/// [`DataType`]: arrow_schema::DataType
+#[macro_export]
+macro_rules! downcast_primitive {
+    ($($data_type:expr),+ => ($m:path $(, $args:tt)*), $($($p:pat),+ => $fallback:expr $(,)*)*) => {
+        $crate::downcast_integer! {
+            $($data_type),+ => ($m $(, $args)*),
+            $crate::repeat_pat!(arrow_schema::DataType::Float16, $($data_type),+) => {
+                $m!($crate::types::Float16Type $(, $args)*)
             }
-            $crate::repeat_pat!(arrow_schema::DataType::Float32, $($values),+) => {
-                $(let $values = $crate::cast::as_primitive_array::<
-                    $crate::types::Float32Type,
-                >($values);)+
-                $e
+            $crate::repeat_pat!(arrow_schema::DataType::Float32, $($data_type),+) => {
+                $m!($crate::types::Float32Type $(, $args)*)
             }
-            $crate::repeat_pat!(arrow_schema::DataType::Float64, $($values),+) => {
-                $(let $values = $crate::cast::as_primitive_array::<
-                    $crate::types::Float64Type,
-                >($values);)+
-                $e
+            $crate::repeat_pat!(arrow_schema::DataType::Float64, $($data_type),+) => {
+                $m!($crate::types::Float64Type $(, $args)*)
             }
-            $crate::repeat_pat!(arrow_schema::DataType::Date32, $($values),+) => {
-                $(let $values = $crate::cast::as_primitive_array::<
-                    $crate::types::Date32Type,
-                >($values);)+
-                $e
+            $crate::repeat_pat!(arrow_schema::DataType::Date32, $($data_type),+) => {
+                $m!($crate::types::Date32Type $(, $args)*)
             }
-            $crate::repeat_pat!(arrow_schema::DataType::Date64, $($values),+) => {
-                $(let $values = $crate::cast::as_primitive_array::<
-                    $crate::types::Date64Type,
-                >($values);)+
-                $e
+            $crate::repeat_pat!(arrow_schema::DataType::Date64, $($data_type),+) => {
+                $m!($crate::types::Date64Type $(, $args)*)
             }
-            $crate::repeat_pat!(arrow_schema::DataType::Time32(arrow_schema::TimeUnit::Second), $($values),+) => {
-                $(let $values = $crate::cast::as_primitive_array::<
-                    $crate::types::Time32SecondType,
-                >($values);)+
-                $e
+            $crate::repeat_pat!(arrow_schema::DataType::Time32(arrow_schema::TimeUnit::Second), $($data_type),+) => {
+                $m!($crate::types::Time32SecondType $(, $args)*)
             }
-            $crate::repeat_pat!(arrow_schema::DataType::Time32(arrow_schema::TimeUnit::Millisecond), $($values),+) => {
-                $(let $values = $crate::cast::as_primitive_array::<
-                    $crate::types::Time32MillisecondType,
-                >($values);)+
-                $e
+            $crate::repeat_pat!(arrow_schema::DataType::Time32(arrow_schema::TimeUnit::Millisecond), $($data_type),+) => {
+                $m!($crate::types::Time32MillisecondType $(, $args)*)
             }
-            $crate::repeat_pat!(arrow_schema::DataType::Time64(arrow_schema::TimeUnit::Microsecond), $($values),+) => {
-                $(let $values = $crate::cast::as_primitive_array::<
-                    $crate::types::Time64MicrosecondType,
-                >($values);)+
-                $e
+            $crate::repeat_pat!(arrow_schema::DataType::Time64(arrow_schema::TimeUnit::Microsecond), $($data_type),+) => {
+                $m!($crate::types::Time64MicrosecondType $(, $args)*)
             }
-            $crate::repeat_pat!(arrow_schema::DataType::Time64(arrow_schema::TimeUnit::Nanosecond), $($values),+) => {
-                $(let $values = $crate::cast::as_primitive_array::<
-                    $crate::types::Time64NanosecondType,
-                >($values);)+
-                $e
+            $crate::repeat_pat!(arrow_schema::DataType::Time64(arrow_schema::TimeUnit::Nanosecond), $($data_type),+) => {
+                $m!($crate::types::Time64NanosecondType $(, $args)*)
             }
-            $crate::repeat_pat!(arrow_schema::DataType::Timestamp(arrow_schema::TimeUnit::Second, _), $($values),+) => {
-                $(let $values = $crate::cast::as_primitive_array::<
-                    $crate::types::TimestampSecondType,
-                >($values);)+
-                $e
+            $crate::repeat_pat!(arrow_schema::DataType::Timestamp(arrow_schema::TimeUnit::Second, _), $($data_type),+) => {
+                $m!($crate::types::TimestampSecondType $(, $args)*)
             }
-            $crate::repeat_pat!(arrow_schema::DataType::Timestamp(arrow_schema::TimeUnit::Millisecond, _), $($values),+) => {
-                $(let $values = $crate::cast::as_primitive_array::<
-                    $crate::types::TimestampMillisecondType,
-                >($values);)+
-                $e
+            $crate::repeat_pat!(arrow_schema::DataType::Timestamp(arrow_schema::TimeUnit::Millisecond, _), $($data_type),+) => {
+                $m!($crate::types::TimestampMillisecondType $(, $args)*)
             }
-            $crate::repeat_pat!(arrow_schema::DataType::Timestamp(arrow_schema::TimeUnit::Microsecond, _), $($values),+) => {
-                $(let $values = $crate::cast::as_primitive_array::<
-                    $crate::types::TimestampMicrosecondType,
-                >($values);)+
-                $e
+            $crate::repeat_pat!(arrow_schema::DataType::Timestamp(arrow_schema::TimeUnit::Microsecond, _), $($data_type),+) => {
+                $m!($crate::types::TimestampMicrosecondType $(, $args)*)
             }
-            $crate::repeat_pat!(arrow_schema::DataType::Timestamp(arrow_schema::TimeUnit::Nanosecond, _), $($values),+) => {
-                $(let $values = $crate::cast::as_primitive_array::<
-                    $crate::types::TimestampNanosecondType,
-                >($values);)+
-                $e
+            $crate::repeat_pat!(arrow_schema::DataType::Timestamp(arrow_schema::TimeUnit::Nanosecond, _), $($data_type),+) => {
+                $m!($crate::types::TimestampNanosecondType $(, $args)*)
             }
-            $crate::repeat_pat!(arrow_schema::DataType::Interval(arrow_schema::IntervalUnit::YearMonth), $($values),+) => {
-                $(let $values = $crate::cast::as_primitive_array::<
-                    $crate::types::IntervalYearMonthType,
-                >($values);)+
-                $e
+            $crate::repeat_pat!(arrow_schema::DataType::Interval(arrow_schema::IntervalUnit::YearMonth), $($data_type),+) => {
+                $m!($crate::types::IntervalYearMonthType $(, $args)*)
             }
-            $crate::repeat_pat!(arrow_schema::DataType::Interval(arrow_schema::IntervalUnit::DayTime), $($values),+) => {
-                $(let $values = $crate::cast::as_primitive_array::<
-                    $crate::types::IntervalDayTimeType,
-                >($values);)+
-                $e
+            $crate::repeat_pat!(arrow_schema::DataType::Interval(arrow_schema::IntervalUnit::DayTime), $($data_type),+) => {
+                $m!($crate::types::IntervalDayTimeType $(, $args)*)
             }
-            $crate::repeat_pat!(arrow_schema::DataType::Interval(arrow_schema::IntervalUnit::MonthDayNano), $($values),+) => {
-                $(let $values = $crate::cast::as_primitive_array::<
-                    $crate::types::IntervalMonthDayNanoType,
-                >($values);)+
-                $e
+            $crate::repeat_pat!(arrow_schema::DataType::Interval(arrow_schema::IntervalUnit::MonthDayNano), $($data_type),+) => {
+                $m!($crate::types::IntervalMonthDayNanoType $(, $args)*)
             }
-            $crate::repeat_pat!(arrow_schema::DataType::Duration(arrow_schema::TimeUnit::Second), $($values),+) => {
-                $(let $values = $crate::cast::as_primitive_array::<
-                    $crate::types::DurationSecondType,
-                >($values);)+
-                $e
+            $crate::repeat_pat!(arrow_schema::DataType::Duration(arrow_schema::TimeUnit::Second), $($data_type),+) => {
+                $m!($crate::types::DurationSecondType $(, $args)*)
             }
-            $crate::repeat_pat!(arrow_schema::DataType::Duration(arrow_schema::TimeUnit::Millisecond), $($values),+) => {
-                $(let $values = $crate::cast::as_primitive_array::<
-                    $crate::types::DurationMillisecondType,
-                >($values);)+
-                $e
+            $crate::repeat_pat!(arrow_schema::DataType::Duration(arrow_schema::TimeUnit::Millisecond), $($data_type),+) => {
+                $m!($crate::types::DurationMillisecondType $(, $args)*)
             }
-            $crate::repeat_pat!(arrow_schema::DataType::Duration(arrow_schema::TimeUnit::Microsecond), $($values),+) => {
-                $(let $values = $crate::cast::as_primitive_array::<
-                    $crate::types::DurationMicrosecondType,
-                >($values);)+
-                $e
+            $crate::repeat_pat!(arrow_schema::DataType::Duration(arrow_schema::TimeUnit::Microsecond), $($data_type),+) => {
+                $m!($crate::types::DurationMicrosecondType $(, $args)*)
             }
-            $crate::repeat_pat!(arrow_schema::DataType::Duration(arrow_schema::TimeUnit::Nanosecond), $($values),+) => {
-                $(let $values = $crate::cast::as_primitive_array::<
-                    $crate::types::DurationNanosecondType,
-                >($values);)+
-                $e
+            $crate::repeat_pat!(arrow_schema::DataType::Duration(arrow_schema::TimeUnit::Nanosecond), $($data_type),+) => {
+                $m!($crate::types::DurationNanosecondType $(, $args)*)
             }
-            $(($($p),+) => $fallback,)*
+            $($($p),+ => $fallback,)*
+        }
+    };
+}
+
+#[macro_export]
+#[doc(hidden)]
+macro_rules! downcast_primitive_array_helper {
+    ($t:ty, $($values:ident),+, $e:block) => {{
+        $(let $values = $crate::cast::as_primitive_array::<$t>($values);)+
+        $e
+    }};
+}
+
+/// Downcast an [`Array`] to a [`PrimitiveArray`] based on its [`DataType`]
+/// accepts a number of subsequent patterns to match the data type
+///
+/// ```
+/// # use arrow_array::{Array, downcast_primitive_array, cast::as_string_array};
+/// # use arrow_schema::DataType;
+///
+/// fn print_primitive(array: &dyn Array) {
+///     downcast_primitive_array!(
+///         array => {
+///             for v in array {
+///                 println!("{:?}", v);
+///             }
+///         }
+///         DataType::Utf8 => {
+///             for v in as_string_array(array) {
+///                 println!("{:?}", v);
+///             }
+///         }
+///         t => println!("Unsupported datatype {}", t)
+///     )
+/// }
+/// ```
+///
+/// [`DataType`]: arrow_schema::DataType
+#[macro_export]
+macro_rules! downcast_primitive_array {
+    ($values:ident => $e:expr, $($p:pat => $fallback:expr $(,)*)*) => {
+        $crate::downcast_primitive_array!($values => {$e} $($p => $fallback)*)
+    };
+    (($($values:ident),+) => $e:block $($($p:pat),+ => $fallback:expr $(,)*)*) => {
+        $crate::downcast_primitive_array!($($values),+ => $e $($($p),+ => $fallback)*)
+    };
+    (($($values:ident),+) => $e:block $(($($p:pat),+) => $fallback:expr $(,)*)*) => {
+        $crate::downcast_primitive_array!($($values),+ => $e $($($p),+ => $fallback)*)
+    };
+    ($($values:ident),+ => $e:block $($($p:pat),+ => $fallback:expr $(,)*)*) => {
+        $crate::downcast_primitive!{
+            $($values.data_type()),+ => ($crate::downcast_primitive_array_helper, $($values),+, $e),
+            $($($p),+ => $fallback,)*
         }
     };
 }
@@ -278,6 +278,15 @@ where
         .expect("Unable to downcast to primitive array")
 }
 
+#[macro_export]
+#[doc(hidden)]
+macro_rules! downcast_dictionary_array_helper {
+    ($t:ty, $($values:ident),+, $e:block) => {{
+        $(let $values = $crate::cast::as_dictionary_array::<$t>($values);)+
+        $e
+    }};
+}
+
 /// Downcast an [`Array`] to a [`DictionaryArray`] based on its [`DataType`], accepts
 /// a number of subsequent patterns to match the data type
 ///
@@ -314,56 +323,11 @@ macro_rules! downcast_dictionary_array {
 
     ($values:ident => $e:block $($p:pat => $fallback:expr $(,)*)*) => {
         match $values.data_type() {
-            arrow_schema::DataType::Dictionary(k, _) => match k.as_ref() {
-                arrow_schema::DataType::Int8 => {
-                    let $values = $crate::cast::as_dictionary_array::<
-                        $crate::types::Int8Type,
-                    >($values);
-                    $e
-                },
-                arrow_schema::DataType::Int16 => {
-                    let $values = $crate::cast::as_dictionary_array::<
-                        $crate::types::Int16Type,
-                    >($values);
-                    $e
-                },
-                arrow_schema::DataType::Int32 => {
-                    let $values = $crate::cast::as_dictionary_array::<
-                        $crate::types::Int32Type,
-                    >($values);
-                    $e
-                },
-                arrow_schema::DataType::Int64 => {
-                    let $values = $crate::cast::as_dictionary_array::<
-                        $crate::types::Int64Type,
-                    >($values);
-                    $e
-                },
-                arrow_schema::DataType::UInt8 => {
-                    let $values = $crate::cast::as_dictionary_array::<
-                        $crate::types::UInt8Type,
-                    >($values);
-                    $e
-                },
-                arrow_schema::DataType::UInt16 => {
-                    let $values = $crate::cast::as_dictionary_array::<
-                        $crate::types::UInt16Type,
-                    >($values);
-                    $e
-                },
-                arrow_schema::DataType::UInt32 => {
-                    let $values = $crate::cast::as_dictionary_array::<
-                        $crate::types::UInt32Type,
-                    >($values);
-                    $e
-                },
-                arrow_schema::DataType::UInt64 => {
-                    let $values = $crate::cast::as_dictionary_array::<
-                        $crate::types::UInt64Type,
-                    >($values);
-                    $e
-                },
-                k => unreachable!("unsupported dictionary key type: {}", k)
+            arrow_schema::DataType::Dictionary(k, _) => {
+                $crate::downcast_integer! {
+                    k.as_ref() => ($crate::downcast_dictionary_array_helper, $values, $e),
+                    k => unreachable!("unsupported dictionary key type: {}", k)
+                }
             }
             $($p => $fallback,)*
         }
diff --git a/arrow/src/row/dictionary.rs b/arrow/src/row/dictionary.rs
index 4a048fbce..b06688224 100644
--- a/arrow/src/row/dictionary.rs
+++ b/arrow/src/row/dictionary.rs
@@ -25,7 +25,7 @@ use arrow_array::types::*;
 use arrow_array::*;
 use arrow_buffer::{ArrowNativeType, MutableBuffer, ToByteSlice};
 use arrow_data::{ArrayData, ArrayDataBuilder};
-use arrow_schema::{ArrowError, DataType, IntervalUnit, TimeUnit};
+use arrow_schema::{ArrowError, DataType};
 use std::collections::hash_map::Entry;
 use std::collections::HashMap;
 
@@ -89,6 +89,12 @@ pub fn encode_dictionary<K: ArrowDictionaryKeyType>(
     }
 }
 
+macro_rules! decode_primitive_helper {
+    ($t:ty, $values: ident) => {
+        decode_primitive::<$t>(&$values)
+    };
+}
+
 /// Decodes a string array from `rows` with the provided `options`
 ///
 /// # Safety
@@ -163,65 +169,10 @@ pub unsafe fn decode_dictionary<K: ArrowDictionaryKeyType>(
         null_builder.append(true);
     }
 
-    let child = match &value_type {
+    let child = downcast_primitive! {
+        &value_type => (decode_primitive_helper, values),
         DataType::Null => NullArray::new(values.len()).into_data(),
         DataType::Boolean => decode_bool(&values),
-        DataType::Int8 => decode_primitive::<Int8Type>(&values),
-        DataType::Int16 => decode_primitive::<Int16Type>(&values),
-        DataType::Int32 => decode_primitive::<Int32Type>(&values),
-        DataType::Int64 => decode_primitive::<Int64Type>(&values),
-        DataType::UInt8 => decode_primitive::<UInt8Type>(&values),
-        DataType::UInt16 => decode_primitive::<UInt16Type>(&values),
-        DataType::UInt32 => decode_primitive::<UInt32Type>(&values),
-        DataType::UInt64 => decode_primitive::<UInt64Type>(&values),
-        DataType::Float16 => decode_primitive::<Float16Type>(&values),
-        DataType::Float32 => decode_primitive::<Float32Type>(&values),
-        DataType::Float64 => decode_primitive::<Float64Type>(&values),
-        DataType::Timestamp(TimeUnit::Second, _) => {
-            decode_primitive::<TimestampSecondType>(&values)
-        }
-        DataType::Timestamp(TimeUnit::Millisecond, _) => {
-            decode_primitive::<TimestampMillisecondType>(&values)
-        }
-        DataType::Timestamp(TimeUnit::Microsecond, _) => {
-            decode_primitive::<TimestampMicrosecondType>(&values)
-        }
-        DataType::Timestamp(TimeUnit::Nanosecond, _) => {
-            decode_primitive::<TimestampNanosecondType>(&values)
-        }
-        DataType::Date32 => decode_primitive::<Date32Type>(&values),
-        DataType::Date64 => decode_primitive::<Date64Type>(&values),
-        DataType::Time32(t) => match t {
-            TimeUnit::Second => decode_primitive::<Time32SecondType>(&values),
-            TimeUnit::Millisecond => decode_primitive::<Time32MillisecondType>(&values),
-            _ => unreachable!(),
-        },
-        DataType::Time64(t) => match t {
-            TimeUnit::Microsecond => decode_primitive::<Time64MicrosecondType>(&values),
-            TimeUnit::Nanosecond => decode_primitive::<Time64NanosecondType>(&values),
-            _ => unreachable!(),
-        },
-        DataType::Duration(TimeUnit::Second) => {
-            decode_primitive::<DurationSecondType>(&values)
-        }
-        DataType::Duration(TimeUnit::Millisecond) => {
-            decode_primitive::<DurationMillisecondType>(&values)
-        }
-        DataType::Duration(TimeUnit::Microsecond) => {
-            decode_primitive::<DurationMicrosecondType>(&values)
-        }
-        DataType::Duration(TimeUnit::Nanosecond) => {
-            decode_primitive::<DurationNanosecondType>(&values)
-        }
-        DataType::Interval(IntervalUnit::DayTime) => {
-            decode_primitive::<IntervalDayTimeType>(&values)
-        }
-        DataType::Interval(IntervalUnit::MonthDayNano) => {
-            decode_primitive::<IntervalMonthDayNanoType>(&values)
-        }
-        DataType::Interval(IntervalUnit::YearMonth) => {
-            decode_primitive::<IntervalYearMonthType>(&values)
-        }
         DataType::Decimal128(p, s) => {
             decode_decimal::<16, Decimal128Type>(&values, *p, *s)
         }
diff --git a/arrow/src/row/mod.rs b/arrow/src/row/mod.rs
index 8d6732054..77c70a5fd 100644
--- a/arrow/src/row/mod.rs
+++ b/arrow/src/row/mod.rs
@@ -616,6 +616,12 @@ fn encode_column(
     }
 }
 
+macro_rules! decode_primitive_helper {
+    ($t:ty, $rows: ident, $options:ident) => {
+        Arc::new(decode_primitive::<$t>($rows, $options))
+    };
+}
+
 /// Decodes a the provided `field` from `rows`
 ///
 /// # Safety
@@ -627,73 +633,10 @@ unsafe fn decode_column(
     interner: Option<&OrderPreservingInterner>,
 ) -> Result<ArrayRef> {
     let options = field.options;
-    let array: ArrayRef = match &field.data_type {
+    let array: ArrayRef = downcast_primitive! {
+        &field.data_type => (decode_primitive_helper, rows, options),
         DataType::Null => Arc::new(NullArray::new(rows.len())),
         DataType::Boolean => Arc::new(decode_bool(rows, options)),
-        DataType::Int8 => Arc::new(decode_primitive::<Int8Type>(rows, options)),
-        DataType::Int16 => Arc::new(decode_primitive::<Int16Type>(rows, options)),
-        DataType::Int32 => Arc::new(decode_primitive::<Int32Type>(rows, options)),
-        DataType::Int64 => Arc::new(decode_primitive::<Int64Type>(rows, options)),
-        DataType::UInt8 => Arc::new(decode_primitive::<UInt8Type>(rows, options)),
-        DataType::UInt16 => Arc::new(decode_primitive::<UInt16Type>(rows, options)),
-        DataType::UInt32 => Arc::new(decode_primitive::<UInt32Type>(rows, options)),
-        DataType::UInt64 => Arc::new(decode_primitive::<UInt64Type>(rows, options)),
-        DataType::Float16 => Arc::new(decode_primitive::<Float16Type>(rows, options)),
-        DataType::Float32 => Arc::new(decode_primitive::<Float32Type>(rows, options)),
-        DataType::Float64 => Arc::new(decode_primitive::<Float64Type>(rows, options)),
-        DataType::Timestamp(TimeUnit::Second, _) => {
-            Arc::new(decode_primitive::<TimestampSecondType>(rows, options))
-        }
-        DataType::Timestamp(TimeUnit::Millisecond, _) => {
-            Arc::new(decode_primitive::<TimestampMillisecondType>(rows, options))
-        }
-        DataType::Timestamp(TimeUnit::Microsecond, _) => {
-            Arc::new(decode_primitive::<TimestampMicrosecondType>(rows, options))
-        }
-        DataType::Timestamp(TimeUnit::Nanosecond, _) => {
-            Arc::new(decode_primitive::<TimestampNanosecondType>(rows, options))
-        }
-        DataType::Date32 => Arc::new(decode_primitive::<Date32Type>(rows, options)),
-        DataType::Date64 => Arc::new(decode_primitive::<Date64Type>(rows, options)),
-        DataType::Time32(t) => match t {
-            TimeUnit::Second => {
-                Arc::new(decode_primitive::<Time32SecondType>(rows, options))
-            }
-            TimeUnit::Millisecond => {
-                Arc::new(decode_primitive::<Time32MillisecondType>(rows, options))
-            }
-            _ => unreachable!(),
-        },
-        DataType::Time64(t) => match t {
-            TimeUnit::Microsecond => {
-                Arc::new(decode_primitive::<Time64MicrosecondType>(rows, options))
-            }
-            TimeUnit::Nanosecond => {
-                Arc::new(decode_primitive::<Time64NanosecondType>(rows, options))
-            }
-            _ => unreachable!(),
-        },
-        DataType::Duration(TimeUnit::Second) => {
-            Arc::new(decode_primitive::<DurationSecondType>(rows, options))
-        }
-        DataType::Duration(TimeUnit::Millisecond) => {
-            Arc::new(decode_primitive::<DurationMillisecondType>(rows, options))
-        }
-        DataType::Duration(TimeUnit::Microsecond) => {
-            Arc::new(decode_primitive::<DurationMicrosecondType>(rows, options))
-        }
-        DataType::Duration(TimeUnit::Nanosecond) => {
-            Arc::new(decode_primitive::<DurationNanosecondType>(rows, options))
-        }
-        DataType::Interval(IntervalUnit::DayTime) => {
-            Arc::new(decode_primitive::<IntervalDayTimeType>(rows, options))
-        }
-        DataType::Interval(IntervalUnit::MonthDayNano) => {
-            Arc::new(decode_primitive::<IntervalMonthDayNanoType>(rows, options))
-        }
-        DataType::Interval(IntervalUnit::YearMonth) => {
-            Arc::new(decode_primitive::<IntervalYearMonthType>(rows, options))
-        }
         DataType::Binary => Arc::new(decode_binary::<i32>(rows, options)),
         DataType::LargeBinary => Arc::new(decode_binary::<i64>(rows, options)),
         DataType::Utf8 => Arc::new(decode_string::<i32>(rows, options)),
@@ -760,13 +703,7 @@ unsafe fn decode_column(
                 )));
             }
         },
-        DataType::FixedSizeBinary(_)
-        | DataType::List(_)
-        | DataType::FixedSizeList(_, _)
-        | DataType::LargeList(_)
-        | DataType::Struct(_)
-        | DataType::Union(_, _, _)
-        | DataType::Map(_, _) => {
+        _ => {
             return Err(ArrowError::NotYetImplemented(format!(
                 "converting {} row is not supported",
                 field.data_type