vortex_layout/
vtable.rs

1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright the Vortex contributors
3
4use std::fmt::Debug;
5use std::ops::Deref;
6use std::sync::Arc;
7
8use vortex_array::ArrayContext;
9use vortex_array::DeserializeMetadata;
10use vortex_array::SerializeMetadata;
11use vortex_dtype::DType;
12use vortex_error::VortexResult;
13use vortex_session::VortexSession;
14
15use crate::IntoLayout;
16use crate::Layout;
17use crate::LayoutChildType;
18use crate::LayoutEncoding;
19use crate::LayoutEncodingRef;
20use crate::LayoutId;
21use crate::LayoutReaderRef;
22use crate::LayoutRef;
23use crate::children::LayoutChildren;
24use crate::segments::SegmentId;
25use crate::segments::SegmentSource;
26
27pub trait VTable: 'static + Sized + Send + Sync + Debug {
28    type Layout: 'static + Send + Sync + Clone + Debug + Deref<Target = dyn Layout> + IntoLayout;
29    type Encoding: 'static + Send + Sync + Deref<Target = dyn LayoutEncoding>;
30    type Metadata: SerializeMetadata + DeserializeMetadata + Debug;
31
32    /// Returns the ID of the layout encoding.
33    fn id(encoding: &Self::Encoding) -> LayoutId;
34
35    /// Returns the encoding for the layout.
36    fn encoding(layout: &Self::Layout) -> LayoutEncodingRef;
37
38    /// Returns the row count for the layout reader.
39    fn row_count(layout: &Self::Layout) -> u64;
40
41    /// Returns the dtype for the layout reader.
42    fn dtype(layout: &Self::Layout) -> &DType;
43
44    /// Returns the metadata for the layout.
45    fn metadata(layout: &Self::Layout) -> Self::Metadata;
46
47    /// Returns the segment IDs for the layout.
48    fn segment_ids(layout: &Self::Layout) -> Vec<SegmentId>;
49
50    /// Returns the number of children for the layout.
51    fn nchildren(layout: &Self::Layout) -> usize;
52
53    /// Return the child at the given index.
54    fn child(layout: &Self::Layout, idx: usize) -> VortexResult<LayoutRef>;
55
56    /// Return the type of the child at the given index.
57    fn child_type(layout: &Self::Layout, idx: usize) -> LayoutChildType;
58
59    /// Create a new reader for the layout.
60    fn new_reader(
61        layout: &Self::Layout,
62        name: Arc<str>,
63        segment_source: Arc<dyn SegmentSource>,
64        session: &VortexSession,
65    ) -> VortexResult<LayoutReaderRef>;
66
67    #[cfg(gpu_unstable)]
68    /// Create a new reader for the layout that uses a gpu device
69    fn new_gpu_reader(
70        layout: &Self::Layout,
71        name: Arc<str>,
72        segment_source: Arc<dyn SegmentSource>,
73        ctx: Arc<cudarc::driver::CudaContext>,
74    ) -> VortexResult<crate::gpu::GpuLayoutReaderRef>;
75
76    /// Construct a new [`Layout`] from the provided parts.
77    fn build(
78        encoding: &Self::Encoding,
79        dtype: &DType,
80        row_count: u64,
81        metadata: &<Self::Metadata as DeserializeMetadata>::Output,
82        segment_ids: Vec<SegmentId>,
83        children: &dyn LayoutChildren,
84        ctx: ArrayContext,
85    ) -> VortexResult<Self::Layout>;
86}
87
88#[macro_export]
89macro_rules! vtable {
90    ($V:ident) => {
91        $crate::aliases::paste::paste! {
92            #[derive(Debug)]
93            pub struct [<$V VTable>];
94
95            impl AsRef<dyn $crate::Layout> for [<$V Layout>] {
96                fn as_ref(&self) -> &dyn $crate::Layout {
97                    // SAFETY: LayoutAdapter is #[repr(transparent)] over the Layout type,
98                    // which guarantees identical memory layout. This cast is safe because
99                    // we're only changing the type metadata, not the actual data.
100                    unsafe { &*(self as *const [<$V Layout>] as *const $crate::LayoutAdapter<[<$V VTable>]>) }
101                }
102            }
103
104            impl std::ops::Deref for [<$V Layout>] {
105                type Target = dyn $crate::Layout;
106
107                fn deref(&self) -> &Self::Target {
108                    // SAFETY: LayoutAdapter is #[repr(transparent)] over the Layout type,
109                    // which guarantees identical memory layout. This cast is safe because
110                    // we're only changing the type metadata, not the actual data.
111                    unsafe { &*(self as *const [<$V Layout>] as *const $crate::LayoutAdapter<[<$V VTable>]>) }
112                }
113            }
114
115            impl $crate::IntoLayout for [<$V Layout>] {
116                fn into_layout(self) -> $crate::LayoutRef {
117                    // SAFETY: LayoutAdapter is #[repr(transparent)] over the Layout type,
118                    // guaranteeing identical memory layout and alignment. The transmute is safe
119                    // because both types have the same size and representation.
120                    std::sync::Arc::new(unsafe { std::mem::transmute::<[<$V Layout>], $crate::LayoutAdapter::<[<$V VTable>]>>(self) })
121                }
122            }
123
124            impl From<[<$V Layout>]> for $crate::LayoutRef {
125                fn from(value: [<$V Layout>]) -> $crate::LayoutRef {
126                    use $crate::IntoLayout;
127                    value.into_layout()
128                }
129            }
130
131            impl AsRef<dyn $crate::LayoutEncoding> for [<$V LayoutEncoding>] {
132                fn as_ref(&self) -> &dyn $crate::LayoutEncoding {
133                    // SAFETY: LayoutEncodingAdapter is #[repr(transparent)] over the LayoutEncoding type,
134                    // which guarantees identical memory layout. This cast is safe because
135                    // we're only changing the type metadata, not the actual data.
136                    unsafe { &*(self as *const [<$V LayoutEncoding>] as *const $crate::LayoutEncodingAdapter<[<$V VTable>]>) }
137                }
138            }
139
140            impl std::ops::Deref for [<$V LayoutEncoding>] {
141                type Target = dyn $crate::LayoutEncoding;
142
143                fn deref(&self) -> &Self::Target {
144                    // SAFETY: LayoutEncodingAdapter is #[repr(transparent)] over the LayoutEncoding type,
145                    // which guarantees identical memory layout. This cast is safe because
146                    // we're only changing the type metadata, not the actual data.
147                    unsafe { &*(self as *const [<$V LayoutEncoding>] as *const $crate::LayoutEncodingAdapter<[<$V VTable>]>) }
148                }
149            }
150        }
151    };
152}