vortex_expr/
vtable.rs

1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright the Vortex contributors
3
4use std::fmt::{Debug, Display};
5use std::hash::Hash;
6use std::ops::Deref;
7
8use vortex_array::{ArrayRef, DeserializeMetadata, SerializeMetadata};
9use vortex_dtype::DType;
10use vortex_error::VortexResult;
11
12use crate::{
13    AnalysisExpr, ExprEncoding, ExprEncodingRef, ExprId, ExprRef, IntoExpr, Scope, VortexExpr,
14};
15
16pub trait VTable: 'static + Sized + Send + Sync + Debug {
17    type Expr: 'static
18        + Send
19        + Sync
20        + Clone
21        + Debug
22        + Display
23        + PartialEq
24        + Hash
25        + Deref<Target = dyn VortexExpr>
26        + IntoExpr
27        + AnalysisExpr;
28    type Encoding: 'static + Send + Sync + Deref<Target = dyn ExprEncoding>;
29    type Metadata: SerializeMetadata + DeserializeMetadata + Debug;
30
31    /// Returns the ID of the expr encoding.
32    fn id(encoding: &Self::Encoding) -> ExprId;
33
34    /// Returns the encoding for the expr.
35    fn encoding(expr: &Self::Expr) -> ExprEncodingRef;
36
37    /// Returns the serialize-able metadata for the expr, or `None` if serialization is not
38    /// supported.
39    fn metadata(expr: &Self::Expr) -> Option<Self::Metadata>;
40
41    /// Returns the children of the expr.
42    fn children(expr: &Self::Expr) -> Vec<&ExprRef>;
43
44    /// Return a new instance of the expression with the children replaced.
45    ///
46    /// ## Preconditions
47    ///
48    /// The number of children will match the current number of children in the expression.
49    fn with_children(expr: &Self::Expr, children: Vec<ExprRef>) -> VortexResult<Self::Expr>;
50
51    /// Construct a new [`VortexExpr`] from the provided parts.
52    fn build(
53        encoding: &Self::Encoding,
54        metadata: &<Self::Metadata as DeserializeMetadata>::Output,
55        children: Vec<ExprRef>,
56    ) -> VortexResult<Self::Expr>;
57
58    /// Evaluate the expression in the given scope.
59    fn evaluate(expr: &Self::Expr, scope: &Scope) -> VortexResult<ArrayRef>;
60
61    /// Compute the return [`DType`] of the expression if evaluated in the given scope.
62    fn return_dtype(expr: &Self::Expr, scope: &DType) -> VortexResult<DType>;
63}
64
65#[macro_export]
66macro_rules! vtable {
67    ($V:ident) => {
68        $crate::aliases::paste::paste! {
69            #[derive(Debug)]
70            pub struct [<$V VTable>];
71
72            impl AsRef<dyn $crate::VortexExpr> for [<$V Expr>] {
73                fn as_ref(&self) -> &dyn $crate::VortexExpr {
74                    // We can unsafe cast ourselves to a ExprAdapter.
75                    unsafe { &*(self as *const [<$V Expr>] as *const $crate::ExprAdapter<[<$V VTable>]>) }
76                }
77            }
78
79            impl std::ops::Deref for [<$V Expr>] {
80                type Target = dyn $crate::VortexExpr;
81
82                fn deref(&self) -> &Self::Target {
83                    // We can unsafe cast ourselves to an ExprAdapter.
84                    unsafe { &*(self as *const [<$V Expr>] as *const $crate::ExprAdapter<[<$V VTable>]>) }
85                }
86            }
87
88            impl $crate::IntoExpr for [<$V Expr>] {
89                fn into_expr(self) -> $crate::ExprRef {
90                    // We can unsafe transmute ourselves to an ExprAdapter.
91                    std::sync::Arc::new(unsafe { std::mem::transmute::<[<$V Expr>], $crate::ExprAdapter::<[<$V VTable>]>>(self) })
92                }
93            }
94
95            impl AsRef<dyn $crate::ExprEncoding> for [<$V ExprEncoding>] {
96                fn as_ref(&self) -> &dyn $crate::ExprEncoding {
97                    // We can unsafe cast ourselves to an ExprEncodingAdapter.
98                    unsafe { &*(self as *const [<$V ExprEncoding>] as *const $crate::ExprEncodingAdapter<[<$V VTable>]>) }
99                }
100            }
101
102            impl std::ops::Deref for [<$V ExprEncoding>] {
103                type Target = dyn $crate::ExprEncoding;
104
105                fn deref(&self) -> &Self::Target {
106                    // We can unsafe cast ourselves to an ExprEncodingAdapter.
107                    unsafe { &*(self as *const [<$V ExprEncoding>] as *const $crate::ExprEncodingAdapter<[<$V VTable>]>) }
108                }
109            }
110        }
111    };
112}