parquet_variant_compute/
type_conversion.rs

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//! Module for transforming a typed arrow `Array` to `VariantArray`.
19
20/// Convert the input array to a `VariantArray` row by row, using `method`
21/// not requiring a generic type to downcast the generic array to a specific
22/// array type and `cast_fn` to transform each element to a type compatible with Variant
23macro_rules! non_generic_conversion_array {
24    ($array:expr, $cast_fn:expr, $builder:expr) => {{
25        let array = $array;
26        for i in 0..array.len() {
27            if array.is_null(i) {
28                $builder.append_null();
29                continue;
30            }
31            let cast_value = $cast_fn(array.value(i));
32            $builder.append_variant(Variant::from(cast_value));
33        }
34    }};
35}
36pub(crate) use non_generic_conversion_array;
37
38/// Convert the value at a specific index in the given array into a `Variant`.
39macro_rules! non_generic_conversion_single_value {
40    ($array:expr, $cast_fn:expr, $index:expr) => {{
41        let array = $array;
42        if array.is_null($index) {
43            Variant::Null
44        } else {
45            let cast_value = $cast_fn(array.value($index));
46            Variant::from(cast_value)
47        }
48    }};
49}
50pub(crate) use non_generic_conversion_single_value;
51
52/// Convert the input array to a `VariantArray` row by row, using `method`
53/// requiring a generic type to downcast the generic array to a specific
54/// array type and `cast_fn` to transform each element to a type compatible with Variant
55macro_rules! generic_conversion_array {
56    ($t:ty, $method:ident, $cast_fn:expr, $input:expr, $builder:expr) => {{
57        $crate::type_conversion::non_generic_conversion_array!(
58            $input.$method::<$t>(),
59            $cast_fn,
60            $builder
61        )
62    }};
63}
64pub(crate) use generic_conversion_array;
65
66/// Convert the value at a specific index in the given array into a `Variant`,
67/// using `method` requiring a generic type to downcast the generic array
68/// to a specific array type and `cast_fn` to transform the element.
69macro_rules! generic_conversion_single_value {
70    ($t:ty, $method:ident, $cast_fn:expr, $input:expr, $index:expr) => {{
71        $crate::type_conversion::non_generic_conversion_single_value!(
72            $input.$method::<$t>(),
73            $cast_fn,
74            $index
75        )
76    }};
77}
78pub(crate) use generic_conversion_single_value;
79
80/// Convert the input array of a specific primitive type to a `VariantArray`
81/// row by row
82macro_rules! primitive_conversion_array {
83    ($t:ty, $input:expr, $builder:expr) => {{
84        $crate::type_conversion::generic_conversion_array!(
85            $t,
86            as_primitive,
87            |v| v,
88            $input,
89            $builder
90        )
91    }};
92}
93pub(crate) use primitive_conversion_array;
94
95/// Convert the value at a specific index in the given array into a `Variant`.
96macro_rules! primitive_conversion_single_value {
97    ($t:ty, $input:expr, $index:expr) => {{
98        $crate::type_conversion::generic_conversion_single_value!(
99            $t,
100            as_primitive,
101            |v| v,
102            $input,
103            $index
104        )
105    }};
106}
107pub(crate) use primitive_conversion_single_value;
108
109/// Convert a decimal value to a `VariantDecimal`
110macro_rules! decimal_to_variant_decimal {
111    ($v:ident, $scale:expr, $value_type:ty, $variant_type:ty) => {{
112        let (v, scale) = if *$scale < 0 {
113            // For negative scale, we need to multiply the value by 10^|scale|
114            // For example: 123 with scale -2 becomes 12300 with scale 0
115            let multiplier = <$value_type>::pow(10, (-*$scale) as u32);
116            (<$value_type>::checked_mul($v, multiplier), 0u8)
117        } else {
118            (Some($v), *$scale as u8)
119        };
120
121        v.and_then(|v| <$variant_type>::try_new(v, scale).ok())
122            .map_or(Variant::Null, Variant::from)
123    }};
124}
125pub(crate) use decimal_to_variant_decimal;