Skip to main content

risingwave_common/types/
macros.rs

1// Copyright 2023 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            { Variant,      Variant,      variant,      $crate::types::VariantVal,  $crate::types::VariantRef<'scalar>, $crate::array::VariantArray,        $crate::array::VariantArrayBuilder      },
59            { Serial,       Serial,       serial,       $crate::types::Serial,      $crate::types::Serial,              $crate::array::SerialArray,         $crate::array::SerialArrayBuilder       },
60            { Struct,       Struct,       struct,       $crate::types::StructValue, $crate::types::StructRef<'scalar>,  $crate::array::StructArray,         $crate::array::StructArrayBuilder       },
61            { List,         List,         list,         $crate::types::ListValue,   $crate::types::ListRef<'scalar>,    $crate::array::ListArray,           $crate::array::ListArrayBuilder         },
62            { Map,          Map,          map,          $crate::types::MapValue,    $crate::types::MapRef<'scalar>,     $crate::array::MapArray,            $crate::array::MapArrayBuilder          },
63            { Vector,       Vector,       vector,       $crate::types::VectorVal,   $crate::types::VectorRef<'scalar>,  $crate::array::VectorArray,         $crate::array::VectorArrayBuilder       },
64            { Bytea,        Bytea,        bytea,        Box<[u8]>,                  &'scalar [u8],                      $crate::array::BytesArray,          $crate::array::BytesArrayBuilder        }
65        }
66    };
67}
68
69/// Helper macro for expanding type aliases and constants. Internally used by `dispatch_` macros.
70#[macro_export]
71macro_rules! do_expand_alias {
72    ($array:ty, $variant_name:ident, (
73        $(Array, $array_alias:ident,)?
74        $(ArrayBuilder, $array_builder_alias:ident,)?
75        $(Scalar, $scalar_alias:ident,)?
76        $(ScalarRef, $scalar_ref_alias:ident,)?
77        $(VARIANT_NAME, $variant_name_alias:ident,)?
78    )) => {
79        $(type $array_alias = $array;)?
80        $(type $array_builder_alias = <$array as $crate::array::Array>::Builder;)?
81        $(type $scalar_alias = <$array as $crate::array::Array>::OwnedItem;)?
82        $(type $scalar_ref_alias<'scalar> = <$array as $crate::array::Array>::RefItem<'scalar>;)?
83        $(const $variant_name_alias: &'static str = stringify!($variant_name);)?
84    };
85}
86
87/// Helper macro for generating dispatching code. Internally used by `dispatch_xx_variants` macros.
88#[macro_export(local_inner_macros)]
89macro_rules! do_dispatch_variants {
90    // Use `tt` for `$alias` as a workaround of nested repetition.
91    ($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 } ),*) => {
92        match $impl {
93            $( $type::$variant_name($inner) => {
94                do_expand_alias!($array, $variant_name, $alias);
95                #[allow(unused_braces)]
96                $body
97            }, )*
98        }
99    };
100}
101
102/// Dispatch the code block to all variants of `ArrayImpl`.
103///
104/// # Usage
105///
106/// The basic usage to access the inner concrete `impl Array` value is:
107///
108/// ```ignore
109/// fn do_stuff<A: Array>(array: &A) { .. }
110///
111/// fn do_stuff_dispatch(array_impl: &ArrayImpl) {
112///     dispatch_array_variants!(array_impl, array, {
113///         do_stuff(array)
114///     })
115/// }
116/// ```
117///
118/// One can also bind the inner concrete `impl Array` type to an alias:
119///
120/// ```ignore
121/// fn do_stuff<A: Array>() { .. }
122///
123/// fn do_stuff_dispatch(array_impl: &ArrayImpl) {
124///     dispatch_array_variants!(array_impl, [A = Array], {
125///         do_stuff::<A>()
126///     })
127/// }
128/// ```
129///
130/// There're more to bind, including type aliases of associated `ArrayBuilder`, `Scalar`, and
131/// `ScalarRef`, or even the constant string of the variant name `VARIANT_NAME`. This can be
132/// achieved by writing one or more of them in the square brackets. Due to the limitation of macro,
133/// the order of the bindings matters.
134///
135/// ```ignore
136/// fn do_stuff_dispatch(array_impl: &ArrayImpl) {
137///     dispatch_array_variants!(
138///         array_impl,
139///         [A = Array, B = ArrayBuilder, S = Scalar, R = ScalarRef, N = VARIANT_NAME],
140///         { .. }
141///     )
142/// }
143/// ```
144///
145/// Alias bindings can also be used along with the inner value accessing:
146///
147/// ```ignore
148/// fn do_stuff<A: Array>(array: &A) { .. }
149///
150/// fn do_stuff_dispatch(array_impl: &ArrayImpl) {
151///     dispatch_array_variants!(array_impl, array, [A = Array], {
152///         do_stuff::<A>(array)
153///     })
154/// }
155/// ```
156#[macro_export(local_inner_macros)]
157macro_rules! dispatch_array_variants {
158    ($impl:expr, [$($k:ident = $v:ident),*], $body:tt) => {
159        dispatch_array_variants!($impl, _, [$($k = $v),*], $body)
160    };
161    ($impl:expr, $inner:pat, $body:tt) => {
162        dispatch_array_variants!($impl, $inner, [], $body)
163    };
164    // Switch the order of alias bindings to avoid ambiguousness.
165    ($impl:expr, $inner:pat, [$($k:ident = $v:ident),*], $body:tt) => {{
166        use $crate::array::ArrayImpl;
167        for_all_variants! { do_dispatch_variants, $impl, ArrayImpl, $inner, [($($v, $k,)*)], $body }
168    }};
169}
170
171/// Dispatch the code block to all variants of `ArrayBuilderImpl`.
172///
173/// Refer to [`dispatch_array_variants`] for usage.
174// TODO: avoid duplication by `macro_metavar_expr` feature
175#[macro_export(local_inner_macros)]
176macro_rules! dispatch_array_builder_variants {
177    ($impl:expr, [$($k:ident = $v:ident),*], $body:tt) => {
178        dispatch_array_builder_variants!($impl, _, [$($k = $v),*], $body)
179    };
180    ($impl:expr, $inner:pat, $body:tt) => {
181        dispatch_array_builder_variants!($impl, $inner, [], $body)
182    };
183    ($impl:expr, $inner:pat, [$($k:ident = $v:ident),*], $body:tt) => {{
184        use $crate::array::ArrayBuilderImpl;
185        for_all_variants! { do_dispatch_variants, $impl, ArrayBuilderImpl, $inner, [($($v, $k,)*)], $body }
186    }};
187}
188
189/// Dispatch the code block to all variants of `ScalarImpl`.
190///
191/// Refer to [`dispatch_array_variants`] for usage.
192// TODO: avoid duplication by `macro_metavar_expr` feature
193#[macro_export(local_inner_macros)]
194macro_rules! dispatch_scalar_variants {
195    ($impl:expr, [$($k:ident = $v:ident),*], $body:tt) => {
196        dispatch_scalar_variants!($impl, _, [$($k = $v),*], $body)
197    };
198    ($impl:expr, $inner:pat, $body:tt) => {
199        dispatch_scalar_variants!($impl, $inner, [], $body)
200    };
201    ($impl:expr, $inner:pat, [$($k:ident = $v:ident),*], $body:tt) => {{
202        use $crate::types::ScalarImpl;
203        for_all_variants! { do_dispatch_variants, $impl, ScalarImpl, $inner, [($($v, $k,)*)], $body }
204    }};
205}
206
207/// Dispatch the code block to all variants of `ScalarRefImpl`.
208///
209/// Refer to [`dispatch_array_variants`] for usage.
210// TODO: avoid duplication by `macro_metavar_expr` feature
211#[macro_export(local_inner_macros)]
212macro_rules! dispatch_scalar_ref_variants {
213    ($impl:expr, [$($k:ident = $v:ident),*], $body:tt) => {
214        dispatch_scalar_ref_variants!($impl, _, [$($k = $v),*], $body)
215    };
216    ($impl:expr, $inner:pat, $body:tt) => {
217        dispatch_scalar_ref_variants!($impl, $inner, [], $body)
218    };
219    ($impl:expr, $inner:pat, [$($k:ident = $v:ident),*], $body:tt) => {{
220        use $crate::types::ScalarRefImpl;
221        for_all_variants! { do_dispatch_variants, $impl, ScalarRefImpl, $inner, [($($v, $k,)*)], $body }
222    }};
223}
224
225/// Helper macro for generating dispatching code. Internally used by `dispatch_data_types` macros.
226#[macro_export(local_inner_macros)]
227macro_rules! do_dispatch_data_types {
228    ($impl:expr, [$alias:tt], $body:tt, $( { $data_type:ident, $variant_name:ident, $suffix_name:ident, $scalar:ty, $scalar_ref:ty, $array:ty, $builder:ty } ),*) => {
229        match $impl {
230            $( $crate::types::DataType::$data_type { .. } => {
231                do_expand_alias!($array, $variant_name, $alias);
232                #[allow(unused_braces)]
233                $body
234            }, )*
235        }
236    };
237}
238
239/// Dispatch the code block to all variants of `DataType`.
240///
241/// There's no inner value to access, so only alias bindings are supported. Refer to
242/// [`dispatch_array_variants`] for usage.
243#[macro_export(local_inner_macros)]
244macro_rules! dispatch_data_types {
245    ($impl:expr, [$($k:ident = $v:ident),*], $body:tt) => {
246        for_all_variants! { do_dispatch_data_types, $impl, [($($v, $k,)*)], $body }
247    };
248}