vortex_array/vtable/mod.rs
1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright the Vortex contributors
3
4//! This module contains the VTable definitions for a Vortex encoding.
5
6mod array;
7mod compute;
8mod decode;
9mod encode;
10mod operations;
11mod serde;
12mod validity;
13mod visitor;
14
15use std::fmt::Debug;
16use std::ops::Deref;
17
18pub use array::*;
19pub use compute::*;
20pub use decode::*;
21pub use encode::*;
22pub use operations::*;
23pub use serde::*;
24pub use validity::*;
25pub use visitor::*;
26
27use crate::{Array, Encoding, EncodingId, EncodingRef, IntoArray};
28
29/// The encoding [`VTable`] encapsulates logic for an Encoding type and associated Array type.
30/// The logic is split across several "VTable" traits to enable easier code organization than
31/// simply lumping everything into a single trait.
32///
33/// Some of these vtables are optional, such as the [`SerdeVTable`], which is only required if
34/// the encoding supports serialization.
35///
36/// From this [`VTable`] trait, we derive implementations for the sealed [`Array`] and [`Encoding`]
37/// traits via the [`crate::ArrayAdapter`] and [`crate::EncodingAdapter`] types respectively.
38///
39/// The functions defined in these vtable traits will typically document their pre- and
40/// post-conditions. The pre-conditions are validated inside the [`Array`] and [`Encoding`]
41/// implementations so do not need to be checked in the vtable implementations (for example, index
42/// out of bounds). Post-conditions are validated after invocation of the vtable function and will
43/// panic if violated.
44pub trait VTable: 'static + Sized + Send + Sync + Debug {
45 type Array: 'static + Send + Sync + Clone + Debug + Deref<Target = dyn Array> + IntoArray;
46 type Encoding: 'static + Send + Sync + Clone + Deref<Target = dyn Encoding>;
47
48 type ArrayVTable: ArrayVTable<Self>;
49 type CanonicalVTable: CanonicalVTable<Self>;
50 type OperationsVTable: OperationsVTable<Self>;
51 type ValidityVTable: ValidityVTable<Self>;
52 type VisitorVTable: VisitorVTable<Self>;
53
54 /// Optionally enable implementing dynamic compute dispatch for this encoding.
55 /// Can be disabled by assigning to the [`NotSupported`] type.
56 type ComputeVTable: ComputeVTable<Self>;
57 /// Optionally enable the [`EncodeVTable`] for this encoding. This allows it to partake in
58 /// compression.
59 /// Can be disabled by assigning to the [`NotSupported`] type.
60 type EncodeVTable: EncodeVTable<Self>;
61 /// Optionally enable serde for this encoding by implementing the [`SerdeVTable`] trait.
62 /// Can be disabled by assigning to the [`NotSupported`] type.
63 type SerdeVTable: SerdeVTable<Self>;
64
65 /// Returns the ID of the encoding.
66 fn id(encoding: &Self::Encoding) -> EncodingId;
67
68 /// Returns the encoding for the array.
69 fn encoding(array: &Self::Array) -> EncodingRef;
70}
71
72/// Placeholder type used to indicate when a particular vtable is not supported by the encoding.
73pub struct NotSupported;
74
75#[macro_export]
76macro_rules! vtable {
77 ($V:ident) => {
78 $crate::aliases::paste::paste! {
79 #[derive(Debug)]
80 pub struct [<$V VTable>];
81
82 impl AsRef<dyn $crate::Array> for [<$V Array>] {
83 fn as_ref(&self) -> &dyn $crate::Array {
84 // We can unsafe cast ourselves to an ArrayAdapter.
85 unsafe { &*(self as *const [<$V Array>] as *const $crate::ArrayAdapter<[<$V VTable>]>) }
86 }
87 }
88
89 impl std::ops::Deref for [<$V Array>] {
90 type Target = dyn $crate::Array;
91
92 fn deref(&self) -> &Self::Target {
93 // We can unsafe cast ourselves to an ArrayAdapter.
94 unsafe { &*(self as *const [<$V Array>] as *const $crate::ArrayAdapter<[<$V VTable>]>) }
95 }
96 }
97
98 impl $crate::IntoArray for [<$V Array>] {
99 fn into_array(self) -> $crate::ArrayRef {
100 // We can unsafe transmute ourselves to an ArrayAdapter.
101 std::sync::Arc::new(unsafe { std::mem::transmute::<[<$V Array>], $crate::ArrayAdapter::<[<$V VTable>]>>(self) })
102 }
103 }
104
105 impl From<[<$V Array>]> for $crate::ArrayRef {
106 fn from(value: [<$V Array>]) -> $crate::ArrayRef {
107 use $crate::IntoArray;
108 value.into_array()
109 }
110 }
111
112 impl AsRef<dyn $crate::Encoding> for [<$V Encoding>] {
113 fn as_ref(&self) -> &dyn $crate::Encoding {
114 // We can unsafe cast ourselves to an EncodingAdapter.
115 unsafe { &*(self as *const [<$V Encoding>] as *const $crate::EncodingAdapter<[<$V VTable>]>) }
116 }
117 }
118
119 impl std::ops::Deref for [<$V Encoding>] {
120 type Target = dyn $crate::Encoding;
121
122 fn deref(&self) -> &Self::Target {
123 // We can unsafe cast ourselves to an EncodingAdapter.
124 unsafe { &*(self as *const [<$V Encoding>] as *const $crate::EncodingAdapter<[<$V VTable>]>) }
125 }
126 }
127 }
128 };
129}