@@ -287,73 +287,71 @@ impl GeoArrowType {
287
287
WktView ( t) => WktView ( t. with_metadata ( meta) ) ,
288
288
}
289
289
}
290
- }
291
-
292
- macro_rules! impl_into_geoarrowtype {
293
- ( $source_type: ident, $variant: expr) => {
294
- impl From <$source_type> for GeoArrowType {
295
- fn from( value: $source_type) -> Self {
296
- $variant( value)
297
- }
298
- }
299
- } ;
300
- }
301
-
302
- impl_into_geoarrowtype ! ( PointType , GeoArrowType :: Point ) ;
303
- impl_into_geoarrowtype ! ( LineStringType , GeoArrowType :: LineString ) ;
304
- impl_into_geoarrowtype ! ( PolygonType , GeoArrowType :: Polygon ) ;
305
- impl_into_geoarrowtype ! ( MultiPointType , GeoArrowType :: MultiPoint ) ;
306
- impl_into_geoarrowtype ! ( MultiLineStringType , GeoArrowType :: MultiLineString ) ;
307
- impl_into_geoarrowtype ! ( MultiPolygonType , GeoArrowType :: MultiPolygon ) ;
308
- impl_into_geoarrowtype ! ( GeometryCollectionType , GeoArrowType :: GeometryCollection ) ;
309
- impl_into_geoarrowtype ! ( BoxType , GeoArrowType :: Rect ) ;
310
- impl_into_geoarrowtype ! ( GeometryType , GeoArrowType :: Geometry ) ;
311
290
312
- impl TryFrom < & Field > for GeoArrowType {
313
- type Error = GeoArrowError ;
291
+ /// Create a new [`GeoArrowType`] from an Arrow [`Field`], requiring GeoArrow metadata to be
292
+ /// set.
293
+ ///
294
+ /// If the field does not have at least a GeoArrow extension name, an error will be returned.
295
+ ///
296
+ /// See also [`GeoArrowType::from_arrow_field`].
297
+ pub fn from_extension_field ( field : & Field ) -> GeoArrowResult < Self > {
298
+ let extension_name = field. extension_type_name ( ) . ok_or ( GeoArrowError :: InvalidGeoArrow (
299
+ "Expected GeoArrow extension metadata, but found none, and `require_geoarrow_metadata` is `true`." . to_string ( ) ,
300
+ ) ) ?;
314
301
315
- fn try_from ( field : & Field ) -> GeoArrowResult < Self > {
316
302
use GeoArrowType :: * ;
317
- if let Some ( extension_name) = field. extension_type_name ( ) {
318
- let data_type = match extension_name {
319
- PointType :: NAME => Point ( field. extension_type ( ) ) ,
320
- LineStringType :: NAME => LineString ( field. extension_type ( ) ) ,
321
- PolygonType :: NAME => Polygon ( field. extension_type ( ) ) ,
322
- MultiPointType :: NAME => MultiPoint ( field. extension_type ( ) ) ,
323
- MultiLineStringType :: NAME => MultiLineString ( field. extension_type ( ) ) ,
324
- MultiPolygonType :: NAME => MultiPolygon ( field. extension_type ( ) ) ,
325
- GeometryCollectionType :: NAME => GeometryCollection ( field. extension_type ( ) ) ,
326
- BoxType :: NAME => Rect ( field. extension_type ( ) ) ,
327
- GeometryType :: NAME => Geometry ( field. extension_type ( ) ) ,
328
- WkbType :: NAME | "ogc.wkb" => match field. data_type ( ) {
329
- DataType :: Binary => Wkb ( field. extension_type ( ) ) ,
330
- DataType :: LargeBinary => LargeWkb ( field. extension_type ( ) ) ,
331
- DataType :: BinaryView => WkbView ( field. extension_type ( ) ) ,
332
- _ => {
333
- return Err ( GeoArrowError :: InvalidGeoArrow ( format ! (
334
- "Expected binary type for geoarrow.wkb, got '{}'" ,
335
- field. data_type( )
336
- ) ) ) ;
337
- }
338
- } ,
339
- WktType :: NAME => match field. data_type ( ) {
340
- DataType :: Utf8 => Wkt ( field. extension_type ( ) ) ,
341
- DataType :: LargeUtf8 => LargeWkt ( field. extension_type ( ) ) ,
342
- DataType :: Utf8View => WktView ( field. extension_type ( ) ) ,
343
- _ => {
344
- return Err ( GeoArrowError :: InvalidGeoArrow ( format ! (
345
- "Expected string type for geoarrow.wkt, got '{}'" ,
346
- field. data_type( )
347
- ) ) ) ;
348
- }
349
- } ,
350
- name => {
303
+ let data_type = match extension_name {
304
+ PointType :: NAME => Point ( field. try_extension_type ( ) ?) ,
305
+ LineStringType :: NAME => LineString ( field. try_extension_type ( ) ?) ,
306
+ PolygonType :: NAME => Polygon ( field. try_extension_type ( ) ?) ,
307
+ MultiPointType :: NAME => MultiPoint ( field. try_extension_type ( ) ?) ,
308
+ MultiLineStringType :: NAME => MultiLineString ( field. try_extension_type ( ) ?) ,
309
+ MultiPolygonType :: NAME => MultiPolygon ( field. try_extension_type ( ) ?) ,
310
+ GeometryCollectionType :: NAME => GeometryCollection ( field. try_extension_type ( ) ?) ,
311
+ BoxType :: NAME => Rect ( field. try_extension_type ( ) ?) ,
312
+ GeometryType :: NAME => Geometry ( field. try_extension_type ( ) ?) ,
313
+ WkbType :: NAME => match field. data_type ( ) {
314
+ DataType :: Binary => Wkb ( field. try_extension_type ( ) ?) ,
315
+ DataType :: LargeBinary => LargeWkb ( field. try_extension_type ( ) ?) ,
316
+ DataType :: BinaryView => WkbView ( field. try_extension_type ( ) ?) ,
317
+ _ => {
351
318
return Err ( GeoArrowError :: InvalidGeoArrow ( format ! (
352
- "Expected GeoArrow type, got Arrow extension type with name: '{name}'." ,
319
+ "Expected binary type for a field with extension name 'geoarrow.wkb', got '{}'" ,
320
+ field. data_type( )
353
321
) ) ) ;
354
322
}
355
- } ;
356
- Ok ( data_type)
323
+ } ,
324
+ WktType :: NAME => match field. data_type ( ) {
325
+ DataType :: Utf8 => Wkt ( field. try_extension_type ( ) ?) ,
326
+ DataType :: LargeUtf8 => LargeWkt ( field. try_extension_type ( ) ?) ,
327
+ DataType :: Utf8View => WktView ( field. try_extension_type ( ) ?) ,
328
+ _ => {
329
+ return Err ( GeoArrowError :: InvalidGeoArrow ( format ! (
330
+ "Expected string type for a field with extension name 'geoarrow.wkt', got '{}'" ,
331
+ field. data_type( )
332
+ ) ) ) ;
333
+ }
334
+ } ,
335
+ name => {
336
+ return Err ( GeoArrowError :: InvalidGeoArrow ( format ! (
337
+ "Expected a GeoArrow extension name, got an Arrow extension type with name: '{name}'." ,
338
+ ) ) ) ;
339
+ }
340
+ } ;
341
+ Ok ( data_type)
342
+ }
343
+
344
+ /// Create a new [`GeoArrowType`] from an Arrow [`Field`], inferring the GeoArrow type if
345
+ /// GeoArrow metadata is not present.
346
+ ///
347
+ /// This will first try [`GeoArrowType::from_extension_field`], and if that fails, will try to
348
+ /// infer the GeoArrow type from the field's [DataType]. This only works for Point, WKB, and
349
+ /// WKT types, as those are the only types that can be unambiguously inferred from an Arrow
350
+ /// [DataType].
351
+ pub fn from_arrow_field ( field : & Field ) -> GeoArrowResult < Self > {
352
+ use GeoArrowType :: * ;
353
+ if let Ok ( geo_type) = Self :: from_extension_field ( field) {
354
+ Ok ( geo_type)
357
355
} else {
358
356
let metadata = Arc :: new ( Metadata :: try_from ( field) ?) ;
359
357
let data_type = match field. data_type ( ) {
@@ -389,7 +387,36 @@ impl TryFrom<&Field> for GeoArrowType {
389
387
DataType :: Utf8View => WktView ( WktType :: new ( metadata) ) ,
390
388
_ => return Err ( GeoArrowError :: InvalidGeoArrow ( "Only FixedSizeList, Struct, Binary, LargeBinary, BinaryView, String, LargeString, and StringView arrays are unambigously typed for a GeoArrow type and can be used without extension metadata.\n Ensure your array input has GeoArrow metadata." . to_string ( ) ) ) ,
391
389
} ;
390
+
392
391
Ok ( data_type)
393
392
}
394
393
}
395
394
}
395
+
396
+ macro_rules! impl_into_geoarrowtype {
397
+ ( $source_type: ident, $variant: expr) => {
398
+ impl From <$source_type> for GeoArrowType {
399
+ fn from( value: $source_type) -> Self {
400
+ $variant( value)
401
+ }
402
+ }
403
+ } ;
404
+ }
405
+
406
+ impl_into_geoarrowtype ! ( PointType , GeoArrowType :: Point ) ;
407
+ impl_into_geoarrowtype ! ( LineStringType , GeoArrowType :: LineString ) ;
408
+ impl_into_geoarrowtype ! ( PolygonType , GeoArrowType :: Polygon ) ;
409
+ impl_into_geoarrowtype ! ( MultiPointType , GeoArrowType :: MultiPoint ) ;
410
+ impl_into_geoarrowtype ! ( MultiLineStringType , GeoArrowType :: MultiLineString ) ;
411
+ impl_into_geoarrowtype ! ( MultiPolygonType , GeoArrowType :: MultiPolygon ) ;
412
+ impl_into_geoarrowtype ! ( GeometryCollectionType , GeoArrowType :: GeometryCollection ) ;
413
+ impl_into_geoarrowtype ! ( BoxType , GeoArrowType :: Rect ) ;
414
+ impl_into_geoarrowtype ! ( GeometryType , GeoArrowType :: Geometry ) ;
415
+
416
+ impl TryFrom < & Field > for GeoArrowType {
417
+ type Error = GeoArrowError ;
418
+
419
+ fn try_from ( field : & Field ) -> GeoArrowResult < Self > {
420
+ Self :: from_extension_field ( field)
421
+ }
422
+ }
0 commit comments