|
10 | 10 | //! For this reason, it's recommended to do as much computation as possible within Vortex, and then
|
11 | 11 | //! materialize an Arrow ArrayRef at the very end of the processing chain.
|
12 | 12 |
|
13 |
| -#[allow(clippy::disallowed_types)] |
14 |
| -use std::collections::HashMap; |
15 | 13 | use std::sync::Arc;
|
16 | 14 |
|
17 | 15 | use arcref::ArcRef;
|
@@ -137,12 +135,13 @@ impl FromArrowType<&Field> for DType {
|
137 | 135 | Some(ext_type) => {
|
138 | 136 | // Check the registry for any Vortex extension types that represent the Arrow
|
139 | 137 | // extension type named here.
|
140 |
| - for converter in inventory::iter::<ArrowToDTypeRef> { |
141 |
| - if converter.0.can_convert(field) { |
142 |
| - return converter |
143 |
| - .0 |
144 |
| - .to_vortex(field) |
145 |
| - .vortex_expect("arrow extension type to vortex dtype"); |
| 138 | + for converter in inventory::iter::<TypeConversionRef> { |
| 139 | + if let Some(converted) = converter |
| 140 | + .0 |
| 141 | + .to_vortex(field) |
| 142 | + .vortex_expect("Conversion from GeoArrow type to GeoVortex") |
| 143 | + { |
| 144 | + return converted; |
146 | 145 | }
|
147 | 146 | }
|
148 | 147 |
|
@@ -210,9 +209,8 @@ impl DType {
|
210 | 209 | // Optionally: attach any Arrow extension type metadata, if an ArrowMetadata
|
211 | 210 | // kernel is defined for the extension type.
|
212 | 211 | if let DType::Extension(ext_type) = field_dt {
|
213 |
| - for kernel in inventory::iter::<ArrowMetadataRef>() { |
214 |
| - if let Some(datum) = kernel.0.arrow_metadata(ext_type.as_ref()) { |
215 |
| - field = field.with_metadata(datum); |
| 212 | + for kernel in inventory::iter::<TypeConversionRef> { |
| 213 | + if kernel.0.to_arrow(ext_type.as_ref(), &mut field)?.is_some() { |
216 | 214 | break;
|
217 | 215 | }
|
218 | 216 | }
|
@@ -242,60 +240,60 @@ impl DType {
|
242 | 240 | }
|
243 | 241 | }
|
244 | 242 |
|
245 |
| -/// Type-erased pointer to a [`ArrowToDType`] implementation. |
246 |
| -pub struct ArrowToDTypeRef(pub ArcRef<dyn ArrowToDType>); |
247 |
| -inventory::collect!(ArrowToDTypeRef); |
248 |
| - |
249 |
| -impl ArrowToDTypeRef { |
250 |
| - /// Attempt to convert a field to a DType. If the there is no registered converter that |
251 |
| - /// can handle the field type, `None` is returned. |
252 |
| - /// |
253 |
| - /// If a converter is resolved, it is used to convert the Field and the result is returned in |
254 |
| - /// a `Some`. |
255 |
| - pub fn convert(field: impl AsRef<Field>) -> Option<VortexResult<DType>> { |
256 |
| - for converter in inventory::iter::<ArrowToDTypeRef> { |
257 |
| - if converter.0.can_convert(field.as_ref()) { |
258 |
| - return Some(converter.0.to_vortex(field.as_ref())); |
259 |
| - } |
| 243 | +/// Attempt to convert a field to a DType. If the there is no registered converter that |
| 244 | +/// can handle the field type, `None` is returned. |
| 245 | +/// |
| 246 | +/// If a converter is resolved, it is used to convert the Field and the result is returned in |
| 247 | +/// a `Some`. |
| 248 | +pub fn geo_field_to_dtype(field: impl AsRef<Field>) -> VortexResult<Option<DType>> { |
| 249 | + for converter in inventory::iter::<TypeConversionRef> { |
| 250 | + if let Some(converted) = converter.0.to_vortex(field.as_ref())? { |
| 251 | + return Ok(Some(converted)); |
260 | 252 | }
|
261 |
| - |
262 |
| - None |
263 | 253 | }
|
264 |
| -} |
265 | 254 |
|
266 |
| -/// Get Arrow extension type metadata for a type. |
267 |
| -pub trait ArrowMetadata: 'static + Send + Sync { |
268 |
| - /// Optionally get the Arrow metadata for this type. None indicates it is not an Arrow |
269 |
| - /// extension type, Some indicates that it is. |
270 |
| - #[allow(clippy::disallowed_types)] |
271 |
| - fn arrow_metadata(&self, vortex_extension_type: &ExtDType) -> Option<HashMap<String, String>>; |
| 255 | + Ok(None) |
272 | 256 | }
|
273 | 257 |
|
274 |
| -/// Type-erased pointer to a thing that can implement the DType conversion instead. |
275 |
| -pub struct ArrowMetadataRef(pub ArcRef<dyn ArrowMetadata>); |
276 |
| -inventory::collect!(ArrowMetadataRef); |
277 |
| - |
278 |
| -/// Conversion for extension types. |
| 258 | +/// Conversions between Arrow [`Field`] type and Vortex logical `DType`. |
279 | 259 | ///
|
280 |
| -/// If we have custom conversions we can register them via a plugin. This is something that is |
281 |
| -/// determined elsewhere however. |
282 |
| -pub trait ArrowToDType: Send + Sync { |
283 |
| - /// If this returns `true`, the implementor is able to convert the given Vortex [`DType`] to |
284 |
| - /// an Arrow [`Field`]. The caller can then call the `to_vortex` method with the argument. |
285 |
| - fn can_convert(&self, data_type: &Field) -> bool; |
286 |
| - |
| 260 | +/// This crate provides infra for registering and discovering extension types. |
| 261 | +/// Once you implement this trait, you need to register it using [`register_extension_type`] |
| 262 | +/// to have it get discovered. |
| 263 | +/// |
| 264 | +/// See also: [`register_extension_type`] |
| 265 | +pub trait TypeConversion: 'static + Send + Sync { |
287 | 266 | /// Convert the given Arrow [`Field`] to a Vortex [`DType`].
|
288 |
| - fn to_vortex(&self, field: &Field) -> VortexResult<DType>; |
| 267 | + fn to_vortex(&self, _field: &Field) -> VortexResult<Option<DType>> { |
| 268 | + Ok(None) |
| 269 | + } |
| 270 | + |
| 271 | + /// Convert a Vortex [`ExtDType`] to an Arrow schema [`Field`]. |
| 272 | + /// |
| 273 | + /// The returned field will have the type, nullability, and metadata |
| 274 | + /// that should be propagated forward, but its name may be changed. |
| 275 | + fn to_arrow(&self, _dtype: &ExtDType, _field_builder: &mut Field) -> VortexResult<Option<()>> { |
| 276 | + Ok(None) |
| 277 | + } |
289 | 278 | }
|
290 | 279 |
|
291 |
| -/// Register an extension type globally. This should be a type that implements |
292 |
| -/// the [`ArrowToDType`] trait. |
| 280 | +/// Conversion token |
| 281 | +pub struct TypeConversionRef(ArcRef<dyn TypeConversion>); |
| 282 | +inventory::collect!(TypeConversionRef); |
| 283 | + |
| 284 | +impl TypeConversionRef { |
| 285 | + /// Create a new `TypeConversionRef` from a pointer to the implementation. |
| 286 | + pub const fn new(conversion: ArcRef<dyn TypeConversion>) -> Self { |
| 287 | + Self(conversion) |
| 288 | + } |
| 289 | +} |
| 290 | + |
| 291 | +/// Register an extension type for lookup. |
293 | 292 | #[macro_export]
|
294 | 293 | macro_rules! register_extension_type {
|
295 | 294 | ($extension:expr) => {
|
296 |
| - $crate::inventory::submit! { |
297 |
| - $extension |
298 |
| - } |
| 295 | + const _: $crate::arrow::TypeConversionRef = $extension; |
| 296 | + $crate::inventory::submit! { $extension } |
299 | 297 | };
|
300 | 298 | }
|
301 | 299 |
|
|
0 commit comments