vortex_array/vtable/
dyn_.rs1use std::fmt::Debug;
5use std::mem::transmute;
6use std::sync::Arc;
7
8use arcref::ArcRef;
9use vortex_error::VortexExpect;
10use vortex_error::VortexResult;
11use vortex_error::vortex_ensure;
12use vortex_session::VortexSession;
13
14use crate::ArrayAdapter;
15use crate::ArrayRef;
16use crate::DynArray;
17use crate::ExecutionResult;
18use crate::ExecutionStep;
19use crate::IntoArray;
20use crate::buffer::BufferHandle;
21use crate::dtype::DType;
22use crate::executor::ExecutionCtx;
23use crate::serde::ArrayChildren;
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 array = V::build(dtype, len, &metadata, buffers, children)?;
94 assert_eq!(array.len(), len, "Array length mismatch after building");
95 assert_eq!(array.dtype(), dtype, "Array dtype mismatch after building");
96 Ok(array.into_array())
97 }
98
99 fn with_children(&self, array: &ArrayRef, children: Vec<ArrayRef>) -> VortexResult<ArrayRef> {
100 let mut array = array.as_::<V>().clone();
101 V::with_children(&mut array, children)?;
102 Ok(array.into_array())
103 }
104
105 fn reduce(&self, array: &ArrayRef) -> VortexResult<Option<ArrayRef>> {
106 let Some(reduced) = V::reduce(downcast::<V>(array))? else {
107 return Ok(None);
108 };
109 vortex_ensure!(
110 reduced.len() == array.len(),
111 "Reduced array length mismatch from {} to {}",
112 array.encoding_id(),
113 reduced.encoding_id()
114 );
115 vortex_ensure!(
116 reduced.dtype() == array.dtype(),
117 "Reduced array dtype mismatch from {} to {}",
118 array.encoding_id(),
119 reduced.encoding_id()
120 );
121 Ok(Some(reduced))
122 }
123
124 fn reduce_parent(
125 &self,
126 array: &ArrayRef,
127 parent: &ArrayRef,
128 child_idx: usize,
129 ) -> VortexResult<Option<ArrayRef>> {
130 let Some(reduced) = V::reduce_parent(downcast::<V>(array), parent, child_idx)? else {
131 return Ok(None);
132 };
133
134 vortex_ensure!(
135 reduced.len() == parent.len(),
136 "Reduced array length mismatch from {} to {}",
137 parent.encoding_id(),
138 reduced.encoding_id()
139 );
140 vortex_ensure!(
141 reduced.dtype() == parent.dtype(),
142 "Reduced array dtype mismatch from {} to {}",
143 parent.encoding_id(),
144 reduced.encoding_id()
145 );
146
147 Ok(Some(reduced))
148 }
149
150 fn execute(&self, array: ArrayRef, ctx: &mut ExecutionCtx) -> VortexResult<ExecutionResult> {
151 let len = array.len();
153 let dtype = array.dtype().clone();
154 let stats = array.statistics().to_owned();
155
156 let owned = downcast_owned::<V>(array);
157 let result = V::execute(owned, ctx)?;
158
159 if matches!(result.step(), ExecutionStep::Done) {
160 if cfg!(debug_assertions) {
161 vortex_ensure!(
162 result.array().len() == len,
163 "Result length mismatch for {:?}",
164 self
165 );
166 vortex_ensure!(
167 result.array().dtype() == &dtype,
168 "Executed canonical dtype mismatch for {:?}",
169 self
170 );
171 }
172
173 result.array().statistics().set_iter(stats.into_iter());
175 }
176
177 Ok(result)
178 }
179
180 fn execute_parent(
181 &self,
182 array: &ArrayRef,
183 parent: &ArrayRef,
184 child_idx: usize,
185 ctx: &mut ExecutionCtx,
186 ) -> VortexResult<Option<ArrayRef>> {
187 let Some(result) = V::execute_parent(downcast::<V>(array), parent, child_idx, ctx)? else {
188 return Ok(None);
189 };
190
191 if cfg!(debug_assertions) {
192 vortex_ensure!(
193 result.as_ref().len() == parent.len(),
194 "Executed parent canonical length mismatch"
195 );
196 vortex_ensure!(
197 result.as_ref().dtype() == parent.dtype(),
198 "Executed parent canonical dtype mismatch"
199 );
200 }
201
202 Ok(Some(result))
203 }
204}
205
206fn downcast<V: VTable>(array: &ArrayRef) -> &V::Array {
207 array
208 .as_any()
209 .downcast_ref::<ArrayAdapter<V>>()
210 .vortex_expect("Failed to downcast array to expected encoding type")
211 .as_inner()
212}
213
214fn downcast_owned<V: VTable>(array: ArrayRef) -> Arc<V::Array> {
219 let adapter: Arc<ArrayAdapter<V>> = array
220 .as_any_arc()
221 .downcast::<ArrayAdapter<V>>()
222 .ok()
223 .vortex_expect("Failed to downcast array to expected encoding type");
224 unsafe { transmute::<Arc<ArrayAdapter<V>>, Arc<V::Array>>(adapter) }
227}
228
229pub(crate) fn upcast_array<V: VTable>(array: Arc<V::Array>) -> ArrayRef {
234 unsafe { transmute::<Arc<V::Array>, Arc<ArrayAdapter<V>>>(array) }
237}