22// SPDX-FileCopyrightText: Copyright the Vortex contributors
33
44use std:: any:: Any ;
5+ use std:: fmt;
56use std:: fmt:: Debug ;
67use std:: fmt:: Display ;
78use std:: fmt:: Formatter ;
8- use std:: mem:: transmute;
9+ use std:: hash:: Hash ;
10+ use std:: hash:: Hasher ;
911use std:: sync:: Arc ;
1012
1113use arcref:: ArcRef ;
@@ -14,9 +16,11 @@ use vortex_dtype::DType;
1416use vortex_error:: VortexExpect ;
1517use vortex_error:: VortexResult ;
1618use vortex_error:: vortex_bail;
19+ use vortex_error:: vortex_ensure;
1720use vortex_error:: vortex_err;
1821
1922use crate :: Array ;
23+ use crate :: ArrayAdapter ;
2024use crate :: ArrayRef ;
2125use crate :: Canonical ;
2226use crate :: IntoArray ;
@@ -26,17 +30,16 @@ use crate::vtable::VTable;
2630
2731/// ArrayId is a globally unique name for the array's vtable.
2832pub 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.
3238pub 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) ]
6771pub struct ArrayVTableAdapter < V : VTable > ( V ) ;
68-
6972impl < 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
142190impl < 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`.
183285impl < 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