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