vortex_array/vtable/
dyn_.rs1use std::any::type_name;
5use std::fmt;
6use std::fmt::Debug;
7use std::fmt::Formatter;
8use std::marker::PhantomData;
9
10use arcref::ArcRef;
11use vortex_error::VortexExpect;
12use vortex_error::VortexResult;
13use vortex_error::vortex_ensure;
14use vortex_session::VortexSession;
15
16use crate::ArrayAdapter;
17use crate::ArrayRef;
18use crate::DynArray;
19use crate::ExecutionStep;
20use crate::IntoArray;
21use crate::buffer::BufferHandle;
22use crate::dtype::DType;
23use crate::executor::ExecutionCtx;
24use crate::serde::ArrayChildren;
25use crate::vtable::VTable;
26
27pub type ArrayId = ArcRef<str>;
29
30pub trait DynVTable: 'static + private::Sealed + Send + Sync + Debug {
39 #[allow(clippy::too_many_arguments)]
40 fn build(
41 &self,
42 id: ArrayId,
43 dtype: &DType,
44 len: usize,
45 metadata: &[u8],
46 buffers: &[BufferHandle],
47 children: &dyn ArrayChildren,
48 session: &VortexSession,
49 ) -> VortexResult<ArrayRef>;
50 fn with_children(&self, array: &ArrayRef, children: Vec<ArrayRef>) -> VortexResult<ArrayRef>;
51
52 fn reduce(&self, array: &ArrayRef) -> VortexResult<Option<ArrayRef>>;
54
55 fn reduce_parent(
57 &self,
58 array: &ArrayRef,
59 parent: &ArrayRef,
60 child_idx: usize,
61 ) -> VortexResult<Option<ArrayRef>>;
62
63 fn execute(&self, array: &ArrayRef, ctx: &mut ExecutionCtx) -> VortexResult<ExecutionStep>;
65
66 fn execute_parent(
68 &self,
69 array: &ArrayRef,
70 parent: &ArrayRef,
71 child_idx: usize,
72 ctx: &mut ExecutionCtx,
73 ) -> VortexResult<Option<ArrayRef>>;
74}
75
76struct ArrayVTableAdapter<V: VTable>(PhantomData<V>);
79
80impl<V: VTable> DynVTable for ArrayVTableAdapter<V> {
81 fn build(
82 &self,
83 _id: ArrayId,
84 dtype: &DType,
85 len: usize,
86 metadata: &[u8],
87 buffers: &[BufferHandle],
88 children: &dyn ArrayChildren,
89 session: &VortexSession,
90 ) -> VortexResult<ArrayRef> {
91 let metadata = V::deserialize(metadata, dtype, len, buffers, session)?;
92 let array = V::build(dtype, len, &metadata, buffers, children)?;
93 assert_eq!(array.len(), len, "Array length mismatch after building");
94 assert_eq!(array.dtype(), dtype, "Array dtype mismatch after building");
95 Ok(array.into_array())
96 }
97
98 fn with_children(&self, array: &ArrayRef, children: Vec<ArrayRef>) -> VortexResult<ArrayRef> {
99 let mut array = array.as_::<V>().clone();
100 V::with_children(&mut array, children)?;
101 Ok(array.into_array())
102 }
103
104 fn reduce(&self, array: &ArrayRef) -> VortexResult<Option<ArrayRef>> {
105 let Some(reduced) = V::reduce(downcast::<V>(array))? else {
106 return Ok(None);
107 };
108 vortex_ensure!(
109 reduced.len() == array.len(),
110 "Reduced array length mismatch from {} to {}",
111 array.encoding_id(),
112 reduced.encoding_id()
113 );
114 vortex_ensure!(
115 reduced.dtype() == array.dtype(),
116 "Reduced array dtype mismatch from {} to {}",
117 array.encoding_id(),
118 reduced.encoding_id()
119 );
120 Ok(Some(reduced))
121 }
122
123 fn reduce_parent(
124 &self,
125 array: &ArrayRef,
126 parent: &ArrayRef,
127 child_idx: usize,
128 ) -> VortexResult<Option<ArrayRef>> {
129 let Some(reduced) = V::reduce_parent(downcast::<V>(array), parent, child_idx)? else {
130 return Ok(None);
131 };
132
133 vortex_ensure!(
134 reduced.len() == parent.len(),
135 "Reduced array length mismatch from {} to {}",
136 parent.encoding_id(),
137 reduced.encoding_id()
138 );
139 vortex_ensure!(
140 reduced.dtype() == parent.dtype(),
141 "Reduced array dtype mismatch from {} to {}",
142 parent.encoding_id(),
143 reduced.encoding_id()
144 );
145
146 Ok(Some(reduced))
147 }
148
149 fn execute(&self, array: &ArrayRef, ctx: &mut ExecutionCtx) -> VortexResult<ExecutionStep> {
150 let step = V::execute(downcast::<V>(array), ctx)?;
151
152 if let ExecutionStep::Done(ref result) = step {
153 if cfg!(debug_assertions) {
154 vortex_ensure!(
155 result.as_ref().len() == array.len(),
156 "Result length mismatch for {:?}",
157 self
158 );
159 vortex_ensure!(
160 result.as_ref().dtype() == array.dtype(),
161 "Executed canonical dtype mismatch for {:?}",
162 self
163 );
164 }
165
166 result
168 .as_ref()
169 .statistics()
170 .inherit_from(array.statistics());
171 }
172
173 Ok(step)
174 }
175
176 fn execute_parent(
177 &self,
178 array: &ArrayRef,
179 parent: &ArrayRef,
180 child_idx: usize,
181 ctx: &mut ExecutionCtx,
182 ) -> VortexResult<Option<ArrayRef>> {
183 let Some(result) = V::execute_parent(downcast::<V>(array), parent, child_idx, ctx)? else {
184 return Ok(None);
185 };
186
187 if cfg!(debug_assertions) {
188 vortex_ensure!(
189 result.as_ref().len() == parent.len(),
190 "Executed parent canonical length mismatch"
191 );
192 vortex_ensure!(
193 result.as_ref().dtype() == parent.dtype(),
194 "Executed parent canonical dtype mismatch"
195 );
196 }
197
198 Ok(Some(result))
199 }
200}
201
202fn downcast<V: VTable>(array: &ArrayRef) -> &V::Array {
203 array
204 .as_any()
205 .downcast_ref::<ArrayAdapter<V>>()
206 .vortex_expect("Failed to downcast array to expected encoding type")
207 .as_inner()
208}
209
210impl<V: VTable> Debug for ArrayVTableAdapter<V> {
211 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
212 write!(f, "Encoding<{}>", type_name::<V>())
213 }
214}
215
216impl<V: VTable> From<V> for &'static dyn DynVTable {
217 fn from(_vtable: V) -> Self {
218 const { &ArrayVTableAdapter::<V>(PhantomData) }
219 }
220}
221
222pub trait ArrayVTableExt {
223 fn vtable() -> &'static dyn DynVTable;
225}
226
227impl<V: VTable> ArrayVTableExt for V {
228 fn vtable() -> &'static dyn DynVTable {
229 const { &ArrayVTableAdapter::<V>(PhantomData) }
230 }
231}
232
233mod private {
234 use super::ArrayVTableAdapter;
235 use crate::vtable::VTable;
236
237 pub trait Sealed {}
238 impl<V: VTable> Sealed for ArrayVTableAdapter<V> {}
239}