1use std::any::Any;
5use std::fmt;
6use std::fmt::Debug;
7use std::fmt::Display;
8use std::fmt::Formatter;
9use std::hash::Hash;
10use std::hash::Hasher;
11use std::sync::Arc;
12
13use arcref::ArcRef;
14use vortex_dtype::DType;
15use vortex_error::VortexExpect;
16use vortex_error::VortexResult;
17use vortex_error::vortex_bail;
18use vortex_error::vortex_ensure;
19use vortex_error::vortex_err;
20use vortex_vector::Vector;
21use vortex_vector::VectorOps;
22use vortex_vector::vector_matches_dtype;
23
24use crate::Array;
25use crate::ArrayAdapter;
26use crate::ArrayRef;
27use crate::Canonical;
28use crate::IntoArray;
29use crate::buffer::BufferHandle;
30use crate::executor::ExecutionCtx;
31use crate::serde::ArrayChildren;
32use crate::vtable::EncodeVTable;
33use crate::vtable::VTable;
34
35pub type ArrayId = ArcRef<str>;
37
38pub trait DynVTable: 'static + private::Sealed + Send + Sync + Debug {
43 fn as_any(&self) -> &dyn Any;
44
45 fn id(&self) -> ArrayId;
46
47 fn build(
48 &self,
49 dtype: &DType,
50 len: usize,
51 metadata: &[u8],
52 buffers: &[BufferHandle],
53 children: &dyn ArrayChildren,
54 ) -> VortexResult<ArrayRef>;
55 fn with_children(&self, array: &dyn Array, children: Vec<ArrayRef>) -> VortexResult<ArrayRef>;
56 fn encode(&self, input: &Canonical, like: Option<&dyn Array>)
57 -> VortexResult<Option<ArrayRef>>;
58
59 fn reduce(&self, array: &ArrayRef) -> VortexResult<Option<ArrayRef>>;
60 fn reduce_parent(
61 &self,
62 array: &ArrayRef,
63 parent: &ArrayRef,
64 child_idx: usize,
65 ) -> VortexResult<Option<ArrayRef>>;
66
67 fn execute(&self, array: &ArrayRef, ctx: &mut ExecutionCtx) -> VortexResult<Vector>;
68 fn execute_parent(
69 &self,
70 array: &ArrayRef,
71 parent: &ArrayRef,
72 child_idx: usize,
73 ctx: &mut ExecutionCtx,
74 ) -> VortexResult<Option<Vector>>;
75}
76
77#[repr(transparent)]
84pub struct ArrayVTableAdapter<V: VTable>(V);
85impl<V: VTable> DynVTable for ArrayVTableAdapter<V> {
86 fn as_any(&self) -> &dyn Any {
87 self
88 }
89
90 fn id(&self) -> ArrayId {
91 V::id(&self.0)
92 }
93
94 fn build(
95 &self,
96 dtype: &DType,
97 len: usize,
98 metadata_bytes: &[u8],
99 buffers: &[BufferHandle],
100 children: &dyn ArrayChildren,
101 ) -> VortexResult<ArrayRef> {
102 let metadata = V::deserialize(metadata_bytes)?;
103 let array = V::build(&self.0, dtype, len, &metadata, buffers, children)?;
104 assert_eq!(array.len(), len, "Array length mismatch after building");
105 assert_eq!(array.dtype(), dtype, "Array dtype mismatch after building");
106 Ok(array.to_array())
107 }
108
109 fn with_children(&self, array: &dyn Array, children: Vec<ArrayRef>) -> VortexResult<ArrayRef> {
110 let mut array = array.as_::<V>().clone();
111 V::with_children(&mut array, children)?;
112 Ok(array.to_array())
113 }
114
115 fn encode(
116 &self,
117 input: &Canonical,
118 like: Option<&dyn Array>,
119 ) -> VortexResult<Option<ArrayRef>> {
120 let downcast_like = like
121 .map(|like| {
122 like.as_opt::<V>().ok_or_else(|| {
123 vortex_err!(
124 "Like array {} does not match requested encoding {}",
125 like.encoding_id(),
126 self.id()
127 )
128 })
129 })
130 .transpose()?;
131
132 let Some(array) =
133 <V::EncodeVTable as EncodeVTable<V>>::encode(&self.0, input, downcast_like)?
134 else {
135 return Ok(None);
136 };
137
138 let input = input.as_ref();
139 if array.len() != input.len() {
140 vortex_bail!(
141 "Array length mismatch after encoding: {} != {}",
142 array.len(),
143 input.len()
144 );
145 }
146 if array.dtype() != input.dtype() {
147 vortex_bail!(
148 "Array dtype mismatch after encoding: {} != {}",
149 array.dtype(),
150 input.dtype()
151 );
152 }
153
154 Ok(Some(array.into_array()))
155 }
156
157 fn reduce(&self, array: &ArrayRef) -> VortexResult<Option<ArrayRef>> {
158 let Some(reduced) = V::reduce(downcast::<V>(array))? else {
159 return Ok(None);
160 };
161 vortex_ensure!(
162 reduced.len() == array.len(),
163 "Reduced array length mismatch from {} to {}",
164 array.display_tree(),
165 reduced.display_tree()
166 );
167 vortex_ensure!(
168 reduced.dtype() == array.dtype(),
169 "Reduced array dtype mismatch from {} to {}",
170 array.display_tree(),
171 reduced.display_tree()
172 );
173 Ok(Some(reduced))
174 }
175
176 fn reduce_parent(
177 &self,
178 array: &ArrayRef,
179 parent: &ArrayRef,
180 child_idx: usize,
181 ) -> VortexResult<Option<ArrayRef>> {
182 let Some(reduced) = V::reduce_parent(downcast::<V>(array), parent, child_idx)? else {
183 return Ok(None);
184 };
185
186 vortex_ensure!(
187 reduced.len() == parent.len(),
188 "Reduced array length mismatch from {} to {}",
189 parent.display_tree(),
190 reduced.display_tree()
191 );
192 vortex_ensure!(
193 reduced.dtype() == parent.dtype(),
194 "Reduced array dtype mismatch from {} to {}",
195 parent.display_tree(),
196 reduced.display_tree()
197 );
198
199 Ok(Some(reduced))
200 }
201
202 fn execute(&self, array: &ArrayRef, ctx: &mut ExecutionCtx) -> VortexResult<Vector> {
203 let result = V::execute(downcast::<V>(array), ctx)?;
204
205 if cfg!(debug_assertions) {
206 vortex_ensure!(
207 result.len() == array.len(),
208 "Result length mismatch for {}",
209 self.id()
210 );
211 vortex_ensure!(
212 vector_matches_dtype(&result, array.dtype()),
213 "Executed vector dtype mismatch for {}",
214 self.id()
215 );
216 }
217
218 Ok(result)
219 }
220
221 fn execute_parent(
222 &self,
223 array: &ArrayRef,
224 parent: &ArrayRef,
225 child_idx: usize,
226 ctx: &mut ExecutionCtx,
227 ) -> VortexResult<Option<Vector>> {
228 let Some(result) = V::execute_parent(downcast::<V>(array), parent, child_idx, ctx)? else {
229 return Ok(None);
230 };
231
232 vortex_ensure!(
233 result.len() == parent.len(),
234 "Executed parent vector length mismatch"
235 );
236 vortex_ensure!(
237 vector_matches_dtype(&result, parent.dtype()),
238 "Executed parent vector dtype mismatch"
239 );
240
241 Ok(Some(result))
242 }
243}
244
245fn downcast<V: VTable>(array: &ArrayRef) -> &V::Array {
246 array
247 .as_any()
248 .downcast_ref::<ArrayAdapter<V>>()
249 .vortex_expect("Invalid options type for expression")
250 .as_inner()
251}
252
253impl<V: VTable> Debug for ArrayVTableAdapter<V> {
254 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
255 f.debug_struct("Encoding").field("id", &self.id()).finish()
256 }
257}
258
259#[derive(Clone)]
261pub struct ArrayVTable(ArcRef<dyn DynVTable>);
262
263impl ArrayVTable {
264 pub(crate) fn as_dyn(&self) -> &dyn DynVTable {
266 self.0.as_ref()
267 }
268
269 pub fn as_any(&self) -> &dyn Any {
271 self.0.as_any()
272 }
273
274 pub fn new<V: VTable>(vtable: V) -> Self {
278 Self(ArcRef::new_arc(Arc::new(ArrayVTableAdapter(vtable))))
279 }
280
281 pub const fn new_static<V: VTable>(vtable: &'static V) -> Self {
283 let adapted: &'static ArrayVTableAdapter<V> =
285 unsafe { &*(vtable as *const V as *const ArrayVTableAdapter<V>) };
286 Self(ArcRef::new_ref(adapted as &'static dyn DynVTable))
287 }
288
289 pub fn id(&self) -> ArrayId {
291 self.0.id()
292 }
293
294 pub fn is<V: VTable>(&self) -> bool {
296 self.0.as_any().is::<V>()
297 }
298
299 pub fn encode(
301 &self,
302 input: &Canonical,
303 like: Option<&dyn Array>,
304 ) -> VortexResult<Option<ArrayRef>> {
305 self.as_dyn().encode(input, like)
306 }
307}
308
309impl PartialEq for ArrayVTable {
310 fn eq(&self, other: &Self) -> bool {
311 self.0.id() == other.0.id()
312 }
313}
314impl Eq for ArrayVTable {}
315
316impl Hash for ArrayVTable {
317 fn hash<H: Hasher>(&self, state: &mut H) {
318 self.0.id().hash(state);
319 }
320}
321
322impl Display for ArrayVTable {
323 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
324 write!(f, "{}", self.as_dyn().id())
325 }
326}
327
328impl Debug for ArrayVTable {
329 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
330 write!(f, "{}", self.as_dyn().id())
331 }
332}
333
334pub trait ArrayVTableExt {
335 fn as_vtable(&'static self) -> ArrayVTable;
337
338 fn into_vtable(self) -> ArrayVTable;
340
341 fn to_vtable(&self) -> ArrayVTable
342 where
343 Self: Clone;
344}
345
346impl<V: VTable> ArrayVTableExt for V {
349 fn as_vtable(&'static self) -> ArrayVTable {
350 ArrayVTable::new_static(self)
351 }
352
353 fn into_vtable(self) -> ArrayVTable {
354 ArrayVTable::new(self)
355 }
356
357 fn to_vtable(&self) -> ArrayVTable
358 where
359 Self: Clone,
360 {
361 ArrayVTable::new(self.clone())
362 }
363}
364
365mod private {
366 use crate::vtable::ArrayVTableAdapter;
367 use crate::vtable::VTable;
368
369 pub trait Sealed {}
370 impl<V: VTable> Sealed for ArrayVTableAdapter<V> {}
371}