1717
1818//! Module for transforming a typed arrow `Array` to `VariantArray`.
1919
20- use arrow:: datatypes:: { self , ArrowPrimitiveType } ;
21- use chrono:: Datelike ;
20+ use arrow:: datatypes:: {
21+ self , ArrowPrimitiveType , ArrowTimestampType , Date32Type , TimestampMicrosecondType ,
22+ TimestampNanosecondType ,
23+ } ;
2224use parquet_variant:: Variant ;
2325
2426/// Options for controlling the behavior of `cast_to_variant_with_options`.
@@ -41,10 +43,12 @@ pub(crate) trait PrimitiveFromVariant: ArrowPrimitiveType {
4143
4244/// Macro to generate PrimitiveFromVariant implementations for Arrow primitive types
4345macro_rules! impl_primitive_from_variant {
44- ( $arrow_type: ty, $variant_method: ident) => {
46+ ( $arrow_type: ty, $variant_method: ident $ ( , $cast_fn : expr ) ? ) => {
4547 impl PrimitiveFromVariant for $arrow_type {
4648 fn from_variant( variant: & Variant <' _, ' _>) -> Option <Self :: Native > {
47- variant. $variant_method( )
49+ let value = variant. $variant_method( ) ;
50+ $( let value = value. map( $cast_fn) ; ) ?
51+ value
4852 }
4953 }
5054 } ;
@@ -61,35 +65,45 @@ impl_primitive_from_variant!(datatypes::UInt64Type, as_u64);
6165impl_primitive_from_variant ! ( datatypes:: Float16Type , as_f16) ;
6266impl_primitive_from_variant ! ( datatypes:: Float32Type , as_f32) ;
6367impl_primitive_from_variant ! ( datatypes:: Float64Type , as_f64) ;
68+ impl_primitive_from_variant ! (
69+ datatypes:: Date32Type ,
70+ as_naive_date,
71+ Date32Type :: from_naive_date
72+ ) ;
6473
65- impl VariantAsPrimitive < datatypes:: TimestampMicrosecondType > for Variant < ' _ , ' _ > {
66- fn as_primitive ( & self ) -> Option < i64 > {
67- match self {
68- Variant :: TimestampMicros ( dt) => Some ( dt. timestamp_micros ( ) ) ,
69- Variant :: TimestampNtzMicros ( ndt) => Some ( ndt. and_utc ( ) . timestamp_micros ( ) ) ,
70- _ => None ,
71- }
72- }
74+ pub ( crate ) trait TimestampFromVariant : ArrowTimestampType {
75+ fn from_variant ( variant : & Variant < ' _ , ' _ > ) -> Option < Self :: Native > ;
7376}
7477
75- impl VariantAsPrimitive < datatypes:: TimestampNanosecondType > for Variant < ' _ , ' _ > {
76- fn as_primitive ( & self ) -> Option < i64 > {
77- match self {
78- Variant :: TimestampNanos ( dt) => dt. timestamp_nanos_opt ( ) ,
79- Variant :: TimestampNtzNanos ( ndt) => ndt. and_utc ( ) . timestamp_nanos_opt ( ) ,
80- _ => None ,
78+ macro_rules! impl_timestamp_from_variant {
79+ ( $timestamp_type: ty, {
80+ $( ( $variant_pattern: pat, $conversion: expr) ) ,+ $( , ) ?
81+ } ) => {
82+ impl TimestampFromVariant for $timestamp_type {
83+ fn from_variant( variant: & Variant <' _, ' _>) -> Option <Self :: Native > {
84+ match variant {
85+ $(
86+ $variant_pattern => $conversion,
87+ ) +
88+ _ => None ,
89+ }
90+ }
8191 }
82- }
92+ } ;
8393}
8494
85- impl VariantAsPrimitive < datatypes:: Date32Type > for Variant < ' _ , ' _ > {
86- fn as_primitive ( & self ) -> Option < i32 > {
87- // The number of days from 0001-01-01 to 1970-01-01.
88- const DAYS_FROM_CE_TO_UNIX_EPOCH : i32 = 719163 ;
89- self . as_naive_date ( )
90- . map ( |d| d. num_days_from_ce ( ) - DAYS_FROM_CE_TO_UNIX_EPOCH )
91- }
92- }
95+ impl_timestamp_from_variant ! ( TimestampMicrosecondType , {
96+ ( Variant :: TimestampMicros ( t) , Some ( t. timestamp_micros( ) ) ) ,
97+ ( Variant :: TimestampNtzMicros ( t) , Some ( t. and_utc( ) . timestamp_micros( ) ) ) ,
98+ } ) ;
99+
100+ impl_timestamp_from_variant ! ( TimestampNanosecondType , {
101+ ( Variant :: TimestampMicros ( t) , Some ( t. timestamp_micros( ) ) . map( |t| t * 1000 ) ) ,
102+ ( Variant :: TimestampNtzMicros ( t) , Some ( t. and_utc( ) . timestamp_micros( ) ) . map( |t| t * 1000 ) ) ,
103+ ( Variant :: TimestampNanos ( t) , t. timestamp_nanos_opt( ) ) ,
104+ ( Variant :: TimestampNtzNanos ( t) , t. and_utc( ) . timestamp_nanos_opt( ) ) ,
105+ } ) ;
106+
93107/// Convert the value at a specific index in the given array into a `Variant`.
94108macro_rules! non_generic_conversion_single_value {
95109 ( $array: expr, $cast_fn: expr, $index: expr) => { {
0 commit comments