44//! Typed and inner representations of extension dtypes.
55//!
66//! - [`ExtDType<V>`]: The public typed wrapper, parameterized by a concrete [`ExtVTable`].
7- //! - [`ExtDTypeInner<V>`]: The private inner struct that holds the vtable + data.
87//! - [`DynExtDType`]: The private sealed trait for type-erased dispatch.
98
109use std:: any:: Any ;
@@ -49,6 +48,7 @@ impl<V: ExtVTable + Default> ExtDType<V> {
4948 }
5049}
5150
51+ #[ allow( clippy:: same_name_method) ]
5252impl < V : ExtVTable > ExtDType < V > {
5353 /// Creates a new extension dtype with the given metadata and storage dtype.
5454 pub fn try_with_vtable (
@@ -87,61 +87,87 @@ impl<V: ExtVTable> ExtDType<V> {
8787 & self . storage_dtype
8888 }
8989
90+ /// Returns a new [`ExtDTypeRef`] with the given nullability.
91+ pub fn with_nullability ( & self , nullability : Nullability ) -> ExtDTypeRef {
92+ let storage_dtype = self . storage_dtype . with_nullability ( nullability) ;
93+ ExtDType :: < V > :: try_with_vtable ( self . vtable . clone ( ) , self . metadata . clone ( ) , storage_dtype)
94+ . vortex_expect (
95+ "Extension DType should not fail validation with the same storage type \
96+ but different nullability",
97+ )
98+ . erased ( )
99+ }
100+
101+ /// Serializes the metadata into a byte vector.
102+ pub fn serialize_metadata ( & self ) -> VortexResult < Vec < u8 > > {
103+ V :: serialize_metadata ( & self . vtable , & self . metadata )
104+ }
105+
106+ /// Validates that the given storage scalar value is valid for this dtype.
107+ pub fn validate_scalar_value ( & self , storage_value : & ScalarValue ) -> VortexResult < ( ) > {
108+ V :: validate_scalar_value ( self , storage_value)
109+ }
110+
111+ /// Can a value of `other` be implicitly coerced into this extension type?
112+ pub fn can_coerce_from ( & self , other : & DType ) -> bool {
113+ V :: can_coerce_from ( self , other)
114+ }
115+
116+ /// Can this extension type be implicitly coerced into `other`?
117+ pub fn can_coerce_to ( & self , other : & DType ) -> bool {
118+ V :: can_coerce_to ( self , other)
119+ }
120+
121+ /// Compute the least supertype of this extension type and another type.
122+ pub fn least_supertype ( & self , other : & DType ) -> Option < DType > {
123+ V :: least_supertype ( self , other)
124+ }
125+
90126 /// Erase the concrete type information, returning a type-erased extension dtype.
91127 pub fn erased ( self ) -> ExtDTypeRef {
92128 ExtDTypeRef ( Arc :: new ( self ) )
93129 }
94130}
95131
96- /// An object-safe, sealed trait encapsulating the behavior for extension dtypes .
132+ /// An object-safe, sealed trait for type-erased extension dtype dispatch .
97133///
98- /// This provides type-erased access to the extension dtype's identity, storage dtype, and
99- /// metadata. The only implementor is [`ExtDTypeInner`].
134+ /// Methods that have a corresponding inherent method on [`ExtDType<V>`] are thin forwarders
135+ /// (e.g. `id`, `storage_dtype`). Methods that exist only for erased dispatch have no
136+ /// inherent counterpart (e.g. `as_any`, `metadata_any`, `metadata_eq`).
100137pub ( super ) trait DynExtDType : ' static + Send + Sync + super :: sealed:: Sealed {
101- /// Returns `self` as a trait object for downcasting.
102138 fn as_any ( & self ) -> & dyn Any ;
103- /// Returns the [`ExtId`] identifying this extension type.
104- fn ext_id ( & self ) -> ExtId ;
105- /// Returns a reference to the storage [`DType`].
106- fn ext_storage_dtype ( & self ) -> & DType ;
107- /// Returns the metadata as a trait object for downcasting.
139+ fn id ( & self ) -> ExtId ;
140+ fn storage_dtype ( & self ) -> & DType ;
108141 fn metadata_any ( & self ) -> & dyn Any ;
109- /// Formats the metadata using [`Debug`].
110142 fn metadata_debug ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result ;
111- /// Formats the metadata using [`Display`].
112143 fn metadata_display ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result ;
113- /// Checks equality of the metadata against a type-erased value.
114144 fn metadata_eq ( & self , other : & dyn Any ) -> bool ;
115- /// Hashes the metadata into the given [`Hasher`].
116145 fn metadata_hash ( & self , state : & mut dyn Hasher ) ;
117- /// Serializes the metadata into a byte vector.
118- fn metadata_serialize ( & self ) -> VortexResult < Vec < u8 > > ;
119- /// Returns a new [`ExtDTypeRef`] with the given nullability.
146+ fn serialize_metadata ( & self ) -> VortexResult < Vec < u8 > > ;
120147 fn with_nullability ( & self , nullability : Nullability ) -> ExtDTypeRef ;
121- /// Validates that the given storage scalar value is valid for this dtype.
122- fn value_validate ( & self , storage_value : & ScalarValue ) -> VortexResult < ( ) > ;
123- /// Formats an extension scalar value using the current dtype for metadata context.
148+ fn validate_scalar_value ( & self , storage_value : & ScalarValue ) -> VortexResult < ( ) > ;
124149 fn value_display ( & self , f : & mut fmt:: Formatter < ' _ > , storage_value : & ScalarValue )
125150 -> fmt:: Result ;
126- /// Can a value of `other` be implicitly coerced into this extension type?
127- fn coercion_can_coerce_from ( & self , other : & DType ) -> bool ;
128- /// Can this extension type be implicitly coerced into `other`?
129- fn coercion_can_coerce_to ( & self , other : & DType ) -> bool ;
130- /// Compute the least supertype of this extension type and another type.
131- fn coercion_least_supertype ( & self , other : & DType ) -> Option < DType > ;
151+ fn can_coerce_from ( & self , other : & DType ) -> bool ;
152+ fn can_coerce_to ( & self , other : & DType ) -> bool ;
153+ fn least_supertype ( & self , other : & DType ) -> Option < DType > ;
132154}
133155
156+ /// Blanket impl: thin forwarder to `ExtDType<V>` inherent methods.
157+ ///
158+ /// Rust's method resolution picks inherent methods over trait methods, so `self.id()` etc.
159+ /// call the inherent impl, not this trait impl (no infinite recursion).
134160impl < V : ExtVTable > DynExtDType for ExtDType < V > {
135161 fn as_any ( & self ) -> & dyn Any {
136162 self
137163 }
138164
139- fn ext_id ( & self ) -> ExtId {
140- self . vtable . id ( )
165+ fn id ( & self ) -> ExtId {
166+ self . id ( )
141167 }
142168
143- fn ext_storage_dtype ( & self ) -> & DType {
144- & self . storage_dtype
169+ fn storage_dtype ( & self ) -> & DType {
170+ self . storage_dtype ( )
145171 }
146172
147173 fn metadata_any ( & self ) -> & dyn Any {
@@ -167,22 +193,16 @@ impl<V: ExtVTable> DynExtDType for ExtDType<V> {
167193 <V :: Metadata as Hash >:: hash ( & self . metadata , & mut state) ;
168194 }
169195
170- fn metadata_serialize ( & self ) -> VortexResult < Vec < u8 > > {
171- V :: serialize_metadata ( & self . vtable , & self . metadata )
196+ fn serialize_metadata ( & self ) -> VortexResult < Vec < u8 > > {
197+ self . serialize_metadata ( )
172198 }
173199
174200 fn with_nullability ( & self , nullability : Nullability ) -> ExtDTypeRef {
175- let storage_dtype = self . storage_dtype . with_nullability ( nullability) ;
176- ExtDType :: < V > :: try_with_vtable ( self . vtable . clone ( ) , self . metadata . clone ( ) , storage_dtype)
177- . vortex_expect (
178- "Extension DType should not fail validation with the same storage type \
179- but different nullability",
180- )
181- . erased ( )
201+ self . with_nullability ( nullability)
182202 }
183203
184- fn value_validate ( & self , storage_value : & ScalarValue ) -> VortexResult < ( ) > {
185- V :: validate_scalar_value ( self , storage_value)
204+ fn validate_scalar_value ( & self , storage_value : & ScalarValue ) -> VortexResult < ( ) > {
205+ self . validate_scalar_value ( storage_value)
186206 }
187207
188208 fn value_display (
@@ -201,15 +221,15 @@ impl<V: ExtVTable> DynExtDType for ExtDType<V> {
201221 }
202222 }
203223
204- fn coercion_can_coerce_from ( & self , other : & DType ) -> bool {
205- V :: can_coerce_from ( self , other)
224+ fn can_coerce_from ( & self , other : & DType ) -> bool {
225+ self . can_coerce_from ( other)
206226 }
207227
208- fn coercion_can_coerce_to ( & self , other : & DType ) -> bool {
209- V :: can_coerce_to ( self , other)
228+ fn can_coerce_to ( & self , other : & DType ) -> bool {
229+ self . can_coerce_to ( other)
210230 }
211231
212- fn coercion_least_supertype ( & self , other : & DType ) -> Option < DType > {
213- V :: least_supertype ( self , other)
232+ fn least_supertype ( & self , other : & DType ) -> Option < DType > {
233+ self . least_supertype ( other)
214234 }
215235}
0 commit comments