vortex_vector/
macros.rs

1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright the Vortex contributors
3
4//! Helper macros for working with the different variants of [`Vector`](crate::Vector) and
5//! [`VectorMut`](crate::VectorMut).
6
7/// Matches on all variants of [`Vector`] and executes the same code for each variant branch.
8///
9/// This macro eliminates repetitive match statements when implementing operations that need to work
10/// uniformly across all vector type variants.
11///
12/// # Examples
13///
14/// ```
15/// use vortex_vector::Vector;
16/// use vortex_vector::bool::BoolVectorMut;
17/// use vortex_vector::null::NullVector;
18/// use vortex_vector::{VectorOps, VectorMutOps, match_each_vector};
19///
20/// fn get_vector_length(vector: &Vector) -> usize {
21///     match_each_vector!(vector, |v| { v.len() })
22/// }
23///
24/// // Works with `Null` vectors.
25/// let null_vec: Vector = NullVector::new(5).into();
26/// assert_eq!(get_vector_length(&null_vec), 5);
27///
28/// // Works with `Bool` vectors.
29/// let bool_vec: Vector = BoolVectorMut::from_iter([true, false, true].map(Some))
30///     .freeze()
31///     .into();
32/// assert_eq!(get_vector_length(&bool_vec), 3);
33/// ```
34///
35/// Note: The `len` method is already provided by the [`VectorOps`] trait implementation.
36///
37/// [`Vector`]: crate::Vector
38/// [`VectorOps`]: crate::VectorOps
39#[macro_export]
40macro_rules! match_each_vector {
41    ($self:expr, | $vec:ident | $body:block) => {{
42        match $self {
43            $crate::Vector::Null($vec) => $body,
44            $crate::Vector::Bool($vec) => $body,
45            $crate::Vector::Decimal($vec) => $body,
46            $crate::Vector::Primitive($vec) => $body,
47            $crate::Vector::String($vec) => $body,
48            $crate::Vector::Binary($vec) => $body,
49            $crate::Vector::List($vec) => $body,
50            $crate::Vector::FixedSizeList($vec) => $body,
51            $crate::Vector::Struct($vec) => $body,
52        }
53    }};
54}
55
56/// Matches on all variants of [`VectorMut`] and executes the same code for each variant branch.
57///
58/// This macro eliminates repetitive match statements when implementing operations that need to work
59/// uniformly across all mutable vector type variants.
60///
61/// # Examples
62///
63/// ```
64/// use vortex_vector::VectorMut;
65/// use vortex_vector::bool::BoolVectorMut;
66/// use vortex_vector::null::NullVectorMut;
67/// use vortex_vector::{VectorMutOps, match_each_vector_mut};
68///
69/// fn reserve_space(vector: &mut VectorMut, additional: usize) {
70///     match_each_vector_mut!(vector, |v| { v.reserve(additional) })
71/// }
72///
73/// // Works with `Null` mutable vectors.
74/// let mut null_vec: VectorMut = NullVectorMut::new(5).into();
75/// reserve_space(&mut null_vec, 10);
76/// assert!(null_vec.capacity() >= 15);
77///
78/// // Works with `Bool` mutable vectors.
79/// let mut bool_vec: VectorMut = BoolVectorMut::from_iter([true, false].map(Some)).into();
80/// reserve_space(&mut bool_vec, 5);
81/// assert!(bool_vec.capacity() >= 7);
82/// ```
83///
84/// Note: The `reserve` method is already provided by the [`VectorMutOps`] trait implementation.
85///
86/// [`VectorMut`]: crate::VectorMut
87/// [`VectorMutOps`]: crate::VectorMutOps
88#[macro_export]
89macro_rules! match_each_vector_mut {
90    ($self:expr, | $vec:ident | $body:block) => {{
91        match $self {
92            $crate::VectorMut::Null($vec) => $body,
93            $crate::VectorMut::Bool($vec) => $body,
94            $crate::VectorMut::Decimal($vec) => $body,
95            $crate::VectorMut::Primitive($vec) => $body,
96            $crate::VectorMut::String($vec) => $body,
97            $crate::VectorMut::Binary($vec) => $body,
98            $crate::VectorMut::List($vec) => $body,
99            $crate::VectorMut::FixedSizeList($vec) => $body,
100            $crate::VectorMut::Struct($vec) => $body,
101        }
102    }};
103}
104
105/// Internal macro to generate match arms for vector pairs.
106#[doc(hidden)]
107#[macro_export]
108macro_rules! __match_vector_pair_arms {
109    (
110        $left:expr,
111        $right:expr,
112        $enum_left:ident,
113        $enum_right:ident,
114        $a:ident,
115        $b:ident,
116        $body:expr
117    ) => {{
118        match ($left, $right) {
119            ($crate::$enum_left::Null($a), $crate::$enum_right::Null($b)) => $body,
120            ($crate::$enum_left::Bool($a), $crate::$enum_right::Bool($b)) => $body,
121            ($crate::$enum_left::Decimal($a), $crate::$enum_right::Decimal($b)) => $body,
122            ($crate::$enum_left::Primitive($a), $crate::$enum_right::Primitive($b)) => $body,
123            ($crate::$enum_left::String($a), $crate::$enum_right::String($b)) => $body,
124            ($crate::$enum_left::Binary($a), $crate::$enum_right::Binary($b)) => $body,
125            ($crate::$enum_left::List($a), $crate::$enum_right::List($b)) => $body,
126            ($crate::$enum_left::FixedSizeList($a), $crate::$enum_right::FixedSizeList($b)) => {
127                $body
128            }
129            ($crate::$enum_left::Struct($a), $crate::$enum_right::Struct($b)) => $body,
130            _ => ::vortex_error::vortex_panic!("Mismatched vector types"),
131        }
132    }};
133}
134
135/// Matches on pairs of vector variants and executes the same code for matching variant pairs.
136///
137/// This macro eliminates repetitive match statements when implementing operations that need to work
138/// with pairs of vectors where the variants must match.
139///
140/// Specify the types of the left and right vectors (either `Vector` or `VectorMut`) and the macro
141/// generates the appropriate match arms.
142///
143/// The macro binds the matched inner values to identifiers in the closure that can be used in the
144/// body expression.
145///
146/// # Examples
147///
148/// ```
149/// use vortex_vector::{Vector, VectorMut, VectorMutOps, match_vector_pair};
150/// use vortex_vector::bool::{BoolVector, BoolVectorMut};
151///
152/// fn extend_vector(left: &mut VectorMut, right: &Vector) {
153///     match_vector_pair!(left, right, |a: VectorMut, b: Vector| {
154///         a.extend_from_vector(b);
155///     })
156/// }
157///
158/// let mut mut_vec: VectorMut = BoolVectorMut::from_iter([true, false, true]).into();
159/// let vec: Vector = BoolVectorMut::from_iter([false, true]).freeze().into();
160///
161/// extend_vector(&mut mut_vec, &vec);
162/// assert_eq!(mut_vec.len(), 5);
163/// ```
164///
165/// Note that the vectors can also be owned:
166///
167/// ```
168/// use vortex_vector::{Vector, VectorMut, VectorMutOps, match_vector_pair};
169/// use vortex_vector::bool::{BoolVector, BoolVectorMut};
170///
171/// fn extend_vector_owned(mut dest: VectorMut, src: Vector) -> VectorMut {
172///     match_vector_pair!(&mut dest, src, |a: VectorMut, b: Vector| {
173///         a.extend_from_vector(&b);
174///         dest
175///     })
176/// }
177///
178/// let mut_vec: VectorMut = BoolVectorMut::from_iter([true, false, true]).into();
179/// let vec: Vector = BoolVectorMut::from_iter([false, true]).freeze().into();
180///
181/// let new_bool_mut = extend_vector_owned(mut_vec, vec);
182/// assert_eq!(new_bool_mut.len(), 5);
183/// ```
184#[macro_export] // DO NOT ADD `#[rustfmt::skip]`!!! https://github.com/rust-lang/rust/pull/52234#issuecomment-903419099
185macro_rules! match_vector_pair {
186    ($left:expr, $right:expr, | $a:ident : Vector, $b:ident : Vector | $body:expr) => {{ $crate::__match_vector_pair_arms!($left, $right, Vector, Vector, $a, $b, $body) }};
187    ($left:expr, $right:expr, | $a:ident : Vector, $b:ident : VectorMut | $body:expr) => {{ $crate::__match_vector_pair_arms!($left, $right, Vector, VectorMut, $a, $b, $body) }};
188    ($left:expr, $right:expr, | $a:ident : VectorMut, $b:ident : Vector | $body:expr) => {{ $crate::__match_vector_pair_arms!($left, $right, VectorMut, Vector, $a, $b, $body) }};
189    ($left:expr, $right:expr, | $a:ident : VectorMut, $b:ident : VectorMut | $body:expr) => {{ $crate::__match_vector_pair_arms!($left, $right, VectorMut, VectorMut, $a, $b, $body) }};
190}