risingwave_common/types/
macros.rs

1// Copyright 2025 RisingWave Labs
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15/// `for_all_variants` includes all variants of our type system. If you introduced a new array type
16/// (also known as scalar type or physical type), be sure to add a variant here.
17///
18/// It is used to simplify the boilerplate code of repeating all array types, while each type
19/// has exactly the same code.
20///
21/// Take `Utf8` as an example, the layout of the variant is:
22/// - `$data_type: Varchar` data type variant name, e.g. `DataType::Varchar`
23/// - `$variant_name: Utf8` array type variant name, e.g. `ArrayImpl::Utf8`, `ScalarImpl::Utf8`
24/// - `$suffix_name: utf8` the suffix of some functions, e.g. `ArrayImpl::as_utf8`
25/// - `$scalar: Box<str>` the scalar type, e.g. `ScalarImpl::Utf8(Box<str>)`
26/// - `$scalar_ref: &'scalar str` the scalar reference type, e.g. `ScalarRefImpl::Utf8(&'scalar
27///   str)`
28/// - `$array: Utf8Array` the array type, e.g. `ArrayImpl::Utf8(Utf8Array)`
29/// - `$builder: Utf8ArrayBuilder` the array builder type, e.g.
30///   `ArrayBuilderImpl::Utf8(Utf8ArrayBuilder)`
31///
32/// To use it, one need to provide another macro which accepts arguments in the layout described
33/// above. Refer to the following implementations as examples.
34///
35/// **Note**: See also `dispatch_xx_variants` and `dispatch_data_types` which doesn't require
36/// another macro for the implementation and can be easier to use in most cases.
37#[macro_export]
38macro_rules! for_all_variants {
39    ($macro:ident $(, $x:tt)*) => {
40        $macro! {
41            $($x, )*
42            //data_type     variant_name  suffix_name   scalar                      scalar_ref                          array                               builder
43            { Int16,        Int16,        int16,        i16,                        i16,                                $crate::array::I16Array,            $crate::array::I16ArrayBuilder          },
44            { Int32,        Int32,        int32,        i32,                        i32,                                $crate::array::I32Array,            $crate::array::I32ArrayBuilder          },
45            { Int64,        Int64,        int64,        i64,                        i64,                                $crate::array::I64Array,            $crate::array::I64ArrayBuilder          },
46            { Int256,       Int256,       int256,       $crate::types::Int256,      $crate::types::Int256Ref<'scalar>,  $crate::array::Int256Array,         $crate::array::Int256ArrayBuilder       },
47            { Float32,      Float32,      float32,      $crate::types::F32,         $crate::types::F32,                 $crate::array::F32Array,            $crate::array::F32ArrayBuilder          },
48            { Float64,      Float64,      float64,      $crate::types::F64,         $crate::types::F64,                 $crate::array::F64Array,            $crate::array::F64ArrayBuilder          },
49            { Varchar,      Utf8,         utf8,         Box<str>,                   &'scalar str,                       $crate::array::Utf8Array,           $crate::array::Utf8ArrayBuilder         },
50            { Boolean,      Bool,         bool,         bool,                       bool,                               $crate::array::BoolArray,           $crate::array::BoolArrayBuilder         },
51            { Decimal,      Decimal,      decimal,      $crate::types::Decimal,     $crate::types::Decimal,             $crate::array::DecimalArray,        $crate::array::DecimalArrayBuilder      },
52            { Interval,     Interval,     interval,     $crate::types::Interval,    $crate::types::Interval,            $crate::array::IntervalArray,       $crate::array::IntervalArrayBuilder     },
53            { Date,         Date,         date,         $crate::types::Date,        $crate::types::Date,                $crate::array::DateArray,           $crate::array::DateArrayBuilder         },
54            { Time,         Time,         time,         $crate::types::Time,        $crate::types::Time,                $crate::array::TimeArray,           $crate::array::TimeArrayBuilder         },
55            { Timestamp,    Timestamp,    timestamp,    $crate::types::Timestamp,   $crate::types::Timestamp,           $crate::array::TimestampArray,      $crate::array::TimestampArrayBuilder    },
56            { Timestamptz,  Timestamptz,  timestamptz,  $crate::types::Timestamptz, $crate::types::Timestamptz,         $crate::array::TimestamptzArray,    $crate::array::TimestamptzArrayBuilder  },
57            { Jsonb,        Jsonb,        jsonb,        $crate::types::JsonbVal,    $crate::types::JsonbRef<'scalar>,   $crate::array::JsonbArray,          $crate::array::JsonbArrayBuilder        },
58            { Serial,       Serial,       serial,       $crate::types::Serial,      $crate::types::Serial,              $crate::array::SerialArray,         $crate::array::SerialArrayBuilder       },
59            { Struct,       Struct,       struct,       $crate::types::StructValue, $crate::types::StructRef<'scalar>,  $crate::array::StructArray,         $crate::array::StructArrayBuilder       },
60            { List,         List,         list,         $crate::types::ListValue,   $crate::types::ListRef<'scalar>,    $crate::array::ListArray,           $crate::array::ListArrayBuilder         },
61            { Map,          Map,          map,          $crate::types::MapValue,    $crate::types::MapRef<'scalar>,     $crate::array::MapArray,            $crate::array::MapArrayBuilder         },
62            { Vector,       Vector,       vector,       $crate::types::VectorVal,   $crate::types::VectorRef<'scalar>,  $crate::array::VectorArray,         $crate::array::VectorArrayBuilder       },
63            { Bytea,        Bytea,        bytea,        Box<[u8]>,                  &'scalar [u8],                      $crate::array::BytesArray,          $crate::array::BytesArrayBuilder        }
64        }
65    };
66}
67
68/// Helper macro for expanding type aliases and constants. Internally used by `dispatch_` macros.
69#[macro_export]
70macro_rules! do_expand_alias {
71    ($array:ty, $variant_name:ident, (
72        $(Array, $array_alias:ident,)?
73        $(ArrayBuilder, $array_builder_alias:ident,)?
74        $(Scalar, $scalar_alias:ident,)?
75        $(ScalarRef, $scalar_ref_alias:ident,)?
76        $(VARIANT_NAME, $variant_name_alias:ident,)?
77    )) => {
78        $(type $array_alias = $array;)?
79        $(type $array_builder_alias = <$array as $crate::array::Array>::Builder;)?
80        $(type $scalar_alias = <$array as $crate::array::Array>::OwnedItem;)?
81        $(type $scalar_ref_alias<'scalar> = <$array as $crate::array::Array>::RefItem<'scalar>;)?
82        $(const $variant_name_alias: &'static str = stringify!($variant_name);)?
83    };
84}
85
86/// Helper macro for generating dispatching code. Internally used by `dispatch_xx_variants` macros.
87#[macro_export(local_inner_macros)]
88macro_rules! do_dispatch_variants {
89    // Use `tt` for `$alias` as a workaround of nested repetition.
90    ($impl:expr, $type:ident, $inner:pat, [$alias:tt], $body:tt, $( { $data_type:ident, $variant_name:ident, $suffix_name:ident, $scalar:ty, $scalar_ref:ty, $array:ty, $builder:ty } ),*) => {
91        match $impl {
92            $( $type::$variant_name($inner) => {
93                do_expand_alias!($array, $variant_name, $alias);
94                #[allow(unused_braces)]
95                $body
96            }, )*
97        }
98    };
99}
100
101/// Dispatch the code block to all variants of `ArrayImpl`.
102///
103/// # Usage
104///
105/// The basic usage to access the inner concrete `impl Array` value is:
106///
107/// ```ignore
108/// fn do_stuff<A: Array>(array: &A) { .. }
109///
110/// fn do_stuff_dispatch(array_impl: &ArrayImpl) {
111///     dispatch_array_variants!(array_impl, array, {
112///         do_stuff(array)
113///     })
114/// }
115/// ```
116///
117/// One can also bind the inner concrete `impl Array` type to an alias:
118///
119/// ```ignore
120/// fn do_stuff<A: Array>() { .. }
121///
122/// fn do_stuff_dispatch(array_impl: &ArrayImpl) {
123///     dispatch_array_variants!(array_impl, [A = Array], {
124///         do_stuff::<A>()
125///     })
126/// }
127/// ```
128///
129/// There're more to bind, including type aliases of associated `ArrayBuilder`, `Scalar`, and
130/// `ScalarRef`, or even the constant string of the variant name `VARIANT_NAME`. This can be
131/// achieved by writing one or more of them in the square brackets. Due to the limitation of macro,
132/// the order of the bindings matters.
133///
134/// ```ignore
135/// fn do_stuff_dispatch(array_impl: &ArrayImpl) {
136///     dispatch_array_variants!(
137///         array_impl,
138///         [A = Array, B = ArrayBuilder, S = Scalar, R = ScalarRef, N = VARIANT_NAME],
139///         { .. }
140///     )
141/// }
142/// ```
143///
144/// Alias bindings can also be used along with the inner value accessing:
145///
146/// ```ignore
147/// fn do_stuff<A: Array>(array: &A) { .. }
148///
149/// fn do_stuff_dispatch(array_impl: &ArrayImpl) {
150///     dispatch_array_variants!(array_impl, array, [A = Array], {
151///         do_stuff::<A>(array)
152///     })
153/// }
154/// ```
155#[macro_export(local_inner_macros)]
156macro_rules! dispatch_array_variants {
157    ($impl:expr, [$($k:ident = $v:ident),*], $body:tt) => {
158        dispatch_array_variants!($impl, _, [$($k = $v),*], $body)
159    };
160    ($impl:expr, $inner:pat, $body:tt) => {
161        dispatch_array_variants!($impl, $inner, [], $body)
162    };
163    // Switch the order of alias bindings to avoid ambiguousness.
164    ($impl:expr, $inner:pat, [$($k:ident = $v:ident),*], $body:tt) => {{
165        use $crate::array::ArrayImpl;
166        for_all_variants! { do_dispatch_variants, $impl, ArrayImpl, $inner, [($($v, $k,)*)], $body }
167    }};
168}
169
170/// Dispatch the code block to all variants of `ArrayBuilderImpl`.
171///
172/// Refer to [`dispatch_array_variants`] for usage.
173// TODO: avoid duplication by `macro_metavar_expr` feature
174#[macro_export(local_inner_macros)]
175macro_rules! dispatch_array_builder_variants {
176    ($impl:expr, [$($k:ident = $v:ident),*], $body:tt) => {
177        dispatch_array_builder_variants!($impl, _, [$($k = $v),*], $body)
178    };
179    ($impl:expr, $inner:pat, $body:tt) => {
180        dispatch_array_builder_variants!($impl, $inner, [], $body)
181    };
182    ($impl:expr, $inner:pat, [$($k:ident = $v:ident),*], $body:tt) => {{
183        use $crate::array::ArrayBuilderImpl;
184        for_all_variants! { do_dispatch_variants, $impl, ArrayBuilderImpl, $inner, [($($v, $k,)*)], $body }
185    }};
186}
187
188/// Dispatch the code block to all variants of `ScalarImpl`.
189///
190/// Refer to [`dispatch_array_variants`] for usage.
191// TODO: avoid duplication by `macro_metavar_expr` feature
192#[macro_export(local_inner_macros)]
193macro_rules! dispatch_scalar_variants {
194    ($impl:expr, [$($k:ident = $v:ident),*], $body:tt) => {
195        dispatch_scalar_variants!($impl, _, [$($k = $v),*], $body)
196    };
197    ($impl:expr, $inner:pat, $body:tt) => {
198        dispatch_scalar_variants!($impl, $inner, [], $body)
199    };
200    ($impl:expr, $inner:pat, [$($k:ident = $v:ident),*], $body:tt) => {{
201        use $crate::types::ScalarImpl;
202        for_all_variants! { do_dispatch_variants, $impl, ScalarImpl, $inner, [($($v, $k,)*)], $body }
203    }};
204}
205
206/// Dispatch the code block to all variants of `ScalarRefImpl`.
207///
208/// Refer to [`dispatch_array_variants`] for usage.
209// TODO: avoid duplication by `macro_metavar_expr` feature
210#[macro_export(local_inner_macros)]
211macro_rules! dispatch_scalar_ref_variants {
212    ($impl:expr, [$($k:ident = $v:ident),*], $body:tt) => {
213        dispatch_scalar_ref_variants!($impl, _, [$($k = $v),*], $body)
214    };
215    ($impl:expr, $inner:pat, $body:tt) => {
216        dispatch_scalar_ref_variants!($impl, $inner, [], $body)
217    };
218    ($impl:expr, $inner:pat, [$($k:ident = $v:ident),*], $body:tt) => {{
219        use $crate::types::ScalarRefImpl;
220        for_all_variants! { do_dispatch_variants, $impl, ScalarRefImpl, $inner, [($($v, $k,)*)], $body }
221    }};
222}
223
224/// Helper macro for generating dispatching code. Internally used by `dispatch_data_types` macros.
225#[macro_export(local_inner_macros)]
226macro_rules! do_dispatch_data_types {
227    ($impl:expr, [$alias:tt], $body:tt, $( { $data_type:ident, $variant_name:ident, $suffix_name:ident, $scalar:ty, $scalar_ref:ty, $array:ty, $builder:ty } ),*) => {
228        match $impl {
229            $( $crate::types::DataType::$data_type { .. } => {
230                do_expand_alias!($array, $variant_name, $alias);
231                #[allow(unused_braces)]
232                $body
233            }, )*
234        }
235    };
236}
237
238/// Dispatch the code block to all variants of `DataType`.
239///
240/// There's no inner value to access, so only alias bindings are supported. Refer to
241/// [`dispatch_array_variants`] for usage.
242#[macro_export(local_inner_macros)]
243macro_rules! dispatch_data_types {
244    ($impl:expr, [$($k:ident = $v:ident),*], $body:tt) => {
245        for_all_variants! { do_dispatch_data_types, $impl, [($($v, $k,)*)], $body }
246    };
247}