Skip to content

Commit a173e90

Browse files
authored
Move reduce / reduce_parent into pub(crate) DynVTable (#5735)
Signed-off-by: Nicholas Gates <[email protected]>
1 parent 5339a58 commit a173e90

File tree

4 files changed

+142
-83
lines changed

4 files changed

+142
-83
lines changed

vortex-array/src/array/mod.rs

Lines changed: 1 addition & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -205,12 +205,6 @@ pub trait Array:
205205
///
206206
/// To invoke the top-level execution, see [`crate::executor::VectorExecutor`].
207207
fn execute(&self, ctx: &mut ExecutionCtx) -> VortexResult<Vector>;
208-
209-
/// Reduce the array to a more simple representation, if possible.
210-
fn reduce(&self) -> VortexResult<Option<ArrayRef>>;
211-
212-
/// Attempt to perform a reduction of the parent of this array.
213-
fn reduce_parent(&self, parent: &ArrayRef, child_idx: usize) -> VortexResult<Option<ArrayRef>>;
214208
}
215209

216210
impl Array for Arc<dyn Array> {
@@ -328,14 +322,6 @@ impl Array for Arc<dyn Array> {
328322
fn execute(&self, ctx: &mut ExecutionCtx) -> VortexResult<Vector> {
329323
self.as_ref().execute(ctx)
330324
}
331-
332-
fn reduce(&self) -> VortexResult<Option<ArrayRef>> {
333-
self.as_ref().reduce()
334-
}
335-
336-
fn reduce_parent(&self, parent: &ArrayRef, child_idx: usize) -> VortexResult<Option<ArrayRef>> {
337-
self.as_ref().reduce_parent(parent, child_idx)
338-
}
339325
}
340326

341327
/// A reference counted pointer to a dynamic [`Array`] trait object.
@@ -455,11 +441,6 @@ impl<V: VTable> ArrayAdapter<V> {
455441
pub fn as_inner(&self) -> &V::Array {
456442
&self.0
457443
}
458-
459-
/// Unwrap into the inner array type, consuming the adapter.
460-
pub fn into_inner(self) -> V::Array {
461-
self.0
462-
}
463444
}
464445

465446
impl<V: VTable> Debug for ArrayAdapter<V> {
@@ -688,7 +669,7 @@ impl<V: VTable> Array for ArrayAdapter<V> {
688669
}
689670

690671
fn with_children(&self, children: Vec<ArrayRef>) -> VortexResult<ArrayRef> {
691-
self.encoding().with_children(self, children)
672+
self.encoding().as_dyn().with_children(self, children)
692673
}
693674

694675
fn invoke(
@@ -717,35 +698,6 @@ impl<V: VTable> Array for ArrayAdapter<V> {
717698

718699
Ok(result)
719700
}
720-
721-
fn reduce(&self) -> VortexResult<Option<ArrayRef>> {
722-
let Some(reduced) = V::reduce(&self.0)? else {
723-
return Ok(None);
724-
};
725-
vortex_ensure!(reduced.len() == self.len(), "Reduced array length mismatch");
726-
vortex_ensure!(
727-
reduced.dtype() == self.dtype(),
728-
"Reduced array dtype mismatch"
729-
);
730-
Ok(Some(reduced))
731-
}
732-
733-
fn reduce_parent(&self, parent: &ArrayRef, child_idx: usize) -> VortexResult<Option<ArrayRef>> {
734-
let Some(reduced) = V::reduce_parent(&self.0, parent, child_idx)? else {
735-
return Ok(None);
736-
};
737-
738-
vortex_ensure!(
739-
reduced.len() == parent.len(),
740-
"Reduced array length mismatch"
741-
);
742-
vortex_ensure!(
743-
reduced.dtype() == parent.dtype(),
744-
"Reduced array dtype mismatch"
745-
);
746-
747-
Ok(Some(reduced))
748-
}
749701
}
750702

751703
impl<V: VTable> ArrayHash for ArrayAdapter<V> {

vortex-array/src/optimizer/mod.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,15 +39,20 @@ fn try_optimize(array: &ArrayRef) -> VortexResult<Option<ArrayRef>> {
3939
}
4040
loop_counter += 1;
4141

42-
if let Some(new_array) = current_array.reduce()? {
42+
if let Some(new_array) = current_array.encoding().as_dyn().reduce(&current_array)? {
4343
current_array = new_array;
4444
any_optimizations = true;
4545
continue;
4646
}
4747

4848
// Apply parent reduction rules to each child in the context of the current array.
4949
for (idx, child) in current_array.children().iter().enumerate() {
50-
if let Some(new_array) = child.reduce_parent(&current_array, idx)? {
50+
if let Some(new_array) =
51+
child
52+
.encoding()
53+
.as_dyn()
54+
.reduce_parent(child, &current_array, idx)?
55+
{
5156
// If the parent was replaced, then we attempt to reduce it again.
5257
current_array = new_array;
5358
any_optimizations = true;

vortex-array/src/serde.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,9 @@ impl ArrayParts {
304304

305305
let children = ArrayPartsChildren { parts: self, ctx };
306306

307-
let decoded = vtable.build(dtype, len, self.metadata(), &buffers, &children)?;
307+
let decoded = vtable
308+
.as_dyn()
309+
.build(dtype, len, self.metadata(), &buffers, &children)?;
308310

309311
assert_eq!(
310312
decoded.len(),

vortex-array/src/vtable/dyn_.rs

Lines changed: 131 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@
22
// SPDX-FileCopyrightText: Copyright the Vortex contributors
33

44
use std::any::Any;
5+
use std::fmt;
56
use std::fmt::Debug;
67
use std::fmt::Display;
78
use std::fmt::Formatter;
8-
use std::mem::transmute;
9+
use std::hash::Hash;
10+
use std::hash::Hasher;
911
use std::sync::Arc;
1012

1113
use arcref::ArcRef;
@@ -14,9 +16,11 @@ use vortex_dtype::DType;
1416
use vortex_error::VortexExpect;
1517
use vortex_error::VortexResult;
1618
use vortex_error::vortex_bail;
19+
use vortex_error::vortex_ensure;
1720
use vortex_error::vortex_err;
1821

1922
use crate::Array;
23+
use crate::ArrayAdapter;
2024
use crate::ArrayRef;
2125
use crate::Canonical;
2226
use crate::IntoArray;
@@ -26,17 +30,16 @@ use crate::vtable::VTable;
2630

2731
/// ArrayId is a globally unique name for the array's vtable.
2832
pub type ArrayId = ArcRef<str>;
29-
pub type ArrayVTable = ArcRef<dyn DynVTable>;
3033

3134
/// Dynamically typed trait for invoking array vtables.
35+
///
36+
/// This trait contains the internal API for Vortex arrays, allowing us to expose things here
37+
/// that we do not want to be part of the public [`Array`] trait.
3238
pub trait DynVTable: 'static + private::Sealed + Send + Sync + Debug {
33-
/// Downcast the encoding to [`Any`].
3439
fn as_any(&self) -> &dyn Any;
3540

36-
/// Returns the ID of the encoding.
3741
fn id(&self) -> ArrayId;
3842

39-
/// Build an array from its parts.
4043
fn build(
4144
&self,
4245
dtype: &DType,
@@ -45,16 +48,17 @@ pub trait DynVTable: 'static + private::Sealed + Send + Sync + Debug {
4548
buffers: &[BufferHandle],
4649
children: &dyn ArrayChildren,
4750
) -> VortexResult<ArrayRef>;
48-
4951
fn with_children(&self, array: &dyn Array, children: Vec<ArrayRef>) -> VortexResult<ArrayRef>;
50-
51-
/// Encode the canonical array into this encoding implementation.
52-
/// Returns `None` if this encoding does not support the given canonical array, for example
53-
/// if the data type is incompatible.
54-
///
55-
/// Panics if `like` is encoded with a different encoding.
5652
fn encode(&self, input: &Canonical, like: Option<&dyn Array>)
5753
-> VortexResult<Option<ArrayRef>>;
54+
55+
fn reduce(&self, array: &ArrayRef) -> VortexResult<Option<ArrayRef>>;
56+
fn reduce_parent(
57+
&self,
58+
array: &ArrayRef,
59+
parent: &ArrayRef,
60+
child_idx: usize,
61+
) -> VortexResult<Option<ArrayRef>>;
5862
}
5963

6064
/// Adapter struct used to lift the [`VTable`] trait into an object-safe [`DynVTable`]
@@ -65,7 +69,6 @@ pub trait DynVTable: 'static + private::Sealed + Send + Sync + Debug {
6569
/// [`AsRef`]. See the `vtable!` macro for more details.
6670
#[repr(transparent)]
6771
pub struct ArrayVTableAdapter<V: VTable>(V);
68-
6972
impl<V: VTable> DynVTable for ArrayVTableAdapter<V> {
7073
fn as_any(&self) -> &dyn Any {
7174
self
@@ -137,34 +140,131 @@ impl<V: VTable> DynVTable for ArrayVTableAdapter<V> {
137140

138141
Ok(Some(array.into_array()))
139142
}
143+
144+
fn reduce(&self, array: &ArrayRef) -> VortexResult<Option<ArrayRef>> {
145+
let Some(reduced) = V::reduce(downcast::<V>(array))? else {
146+
return Ok(None);
147+
};
148+
vortex_ensure!(
149+
reduced.len() == array.len(),
150+
"Reduced array length mismatch"
151+
);
152+
vortex_ensure!(
153+
reduced.dtype() == array.dtype(),
154+
"Reduced array dtype mismatch"
155+
);
156+
Ok(Some(reduced))
157+
}
158+
159+
fn reduce_parent(
160+
&self,
161+
array: &ArrayRef,
162+
parent: &ArrayRef,
163+
child_idx: usize,
164+
) -> VortexResult<Option<ArrayRef>> {
165+
let Some(reduced) = V::reduce_parent(downcast::<V>(array), parent, child_idx)? else {
166+
return Ok(None);
167+
};
168+
169+
vortex_ensure!(
170+
reduced.len() == parent.len(),
171+
"Reduced array length mismatch"
172+
);
173+
vortex_ensure!(
174+
reduced.dtype() == parent.dtype(),
175+
"Reduced array dtype mismatch"
176+
);
177+
178+
Ok(Some(reduced))
179+
}
180+
}
181+
182+
fn downcast<V: VTable>(array: &ArrayRef) -> &V::Array {
183+
array
184+
.as_any()
185+
.downcast_ref::<ArrayAdapter<V>>()
186+
.vortex_expect("Invalid options type for expression")
187+
.as_inner()
140188
}
141189

142190
impl<V: VTable> Debug for ArrayVTableAdapter<V> {
143-
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
191+
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
144192
f.debug_struct("Encoding").field("id", &self.id()).finish()
145193
}
146194
}
147195

148-
impl Display for dyn DynVTable + '_ {
149-
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
150-
write!(f, "{}", self.id())
196+
/// Dynamically typed array vtable.
197+
#[derive(Clone)]
198+
pub struct ArrayVTable(ArcRef<dyn DynVTable>);
199+
200+
impl ArrayVTable {
201+
/// Returns the underlying vtable API, public only within the crate.
202+
pub(crate) fn as_dyn(&self) -> &dyn DynVTable {
203+
self.0.as_ref()
204+
}
205+
206+
/// Return the vtable as an Any reference.
207+
pub fn as_any(&self) -> &dyn Any {
208+
self.0.as_any()
209+
}
210+
211+
/// Creates a new [`ArrayVTable`] from a vtable.
212+
///
213+
/// Prefer to use [`Self::new_static`] when possible.
214+
pub fn new<V: VTable>(vtable: V) -> Self {
215+
Self(ArcRef::new_arc(Arc::new(ArrayVTableAdapter(vtable))))
216+
}
217+
218+
/// Creates a new [`ArrayVTable`] from a static reference to a vtable.
219+
pub const fn new_static<V: VTable>(vtable: &'static V) -> Self {
220+
// SAFETY: We can safely cast the vtable to a VTableAdapter since it has the same layout.
221+
let adapted: &'static ArrayVTableAdapter<V> =
222+
unsafe { &*(vtable as *const V as *const ArrayVTableAdapter<V>) };
223+
Self(ArcRef::new_ref(adapted as &'static dyn DynVTable))
224+
}
225+
226+
/// Returns the ID of this vtable.
227+
pub fn id(&self) -> ArrayId {
228+
self.0.id()
229+
}
230+
231+
/// Returns whether this vtable is of a given type.
232+
pub fn is<V: VTable>(&self) -> bool {
233+
self.0.as_any().is::<V>()
234+
}
235+
236+
/// Encode the canonical array like the given array.
237+
pub fn encode(
238+
&self,
239+
input: &Canonical,
240+
like: Option<&dyn Array>,
241+
) -> VortexResult<Option<ArrayRef>> {
242+
self.as_dyn().encode(input, like)
151243
}
152244
}
153245

154-
impl PartialEq for dyn DynVTable + '_ {
246+
impl PartialEq for ArrayVTable {
155247
fn eq(&self, other: &Self) -> bool {
156-
self.id() == other.id()
248+
self.0.id() == other.0.id()
157249
}
158250
}
251+
impl Eq for ArrayVTable {}
159252

160-
impl Eq for dyn DynVTable + '_ {}
253+
impl Hash for ArrayVTable {
254+
fn hash<H: Hasher>(&self, state: &mut H) {
255+
self.0.id().hash(state);
256+
}
257+
}
258+
259+
impl Display for ArrayVTable {
260+
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
261+
write!(f, "{}", self.as_dyn().id())
262+
}
263+
}
161264

162-
impl dyn DynVTable + '_ {
163-
pub fn as_<V: VTable>(&self) -> &V {
164-
self.as_any()
165-
.downcast_ref::<ArrayVTableAdapter<V>>()
166-
.map(|e| &e.0)
167-
.vortex_expect("Encoding is not of the expected type")
265+
impl Debug for ArrayVTable {
266+
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
267+
write!(f, "{}", self.as_dyn().id())
168268
}
169269
}
170270

@@ -180,22 +280,22 @@ pub trait ArrayVTableExt {
180280
Self: Clone;
181281
}
182282

283+
// TODO(ngates): deprecate these functions in favor of `ArrayVTable::new` and
284+
// `ArrayVTable::new_static`.
183285
impl<V: VTable> ArrayVTableExt for V {
184286
fn as_vtable(&'static self) -> ArrayVTable {
185-
let dyn_vtable: &'static ArrayVTableAdapter<V> =
186-
unsafe { transmute::<&'static V, &'static ArrayVTableAdapter<V>>(self) };
187-
ArrayVTable::new_ref(dyn_vtable)
287+
ArrayVTable::new_static(self)
188288
}
189289

190290
fn into_vtable(self) -> ArrayVTable {
191-
ArrayVTable::new_arc(Arc::new(ArrayVTableAdapter(self)))
291+
ArrayVTable::new(self)
192292
}
193293

194294
fn to_vtable(&self) -> ArrayVTable
195295
where
196296
Self: Clone,
197297
{
198-
ArrayVTable::new_arc(Arc::new(ArrayVTableAdapter(self.clone())))
298+
ArrayVTable::new(self.clone())
199299
}
200300
}
201301

0 commit comments

Comments
 (0)