Skip to content

Commit 929f462

Browse files
committed
feat: Implement mapping from GeoArrow extension types to Polars extension types
1 parent e8d110c commit 929f462

6 files changed

Lines changed: 106 additions & 6 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ arrow-data = { version = "56", features = ["ffi"] }
1919
arrow-schema = "56"
2020
geoarrow-array = "0.6"
2121
geoarrow-schema = "0.6"
22+
geopolars-arrow = { path = "geopolars/geopolars-arrow" }
2223
polars = { git = "https://github.com/pola-rs/polars", rev = "0c6dca54ae4a33b3f31191748ad6a5ffd5452822", features = [
2324
"dtype-extension",
2425
] }

geopolars/geopolars-extension/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,10 @@ arrow-data = { workspace = true }
1818
arrow-schema = { workspace = true }
1919
geoarrow-array = { workspace = true }
2020
geoarrow-schema = { workspace = true }
21+
geopolars-arrow = { workspace = true }
22+
polars = { workspace = true }
2123
polars-arrow = { workspace = true }
2224
polars-core = { workspace = true }
23-
polars = { workspace = true }
2425

2526
[dev-dependencies]
2627
geoarrow-array = { workspace = true, features = ["test-data"] }
Lines changed: 61 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,16 @@
1-
use polars::prelude::DataType;
1+
use std::collections::HashMap;
2+
3+
use geoarrow_schema::GeoArrowType;
4+
use geopolars_arrow::to_arrow::polars_field_to_arrow;
25
use polars::prelude::extension::{ExtensionTypeFactory, ExtensionTypeImpl};
6+
use polars::prelude::{CompatLevel, DataType};
7+
8+
use crate::geoarrow::{
9+
BoxType, GeometryCollectionType, GeometryType, LineStringType, MultiLineStringType,
10+
MultiPointType, MultiPolygonType, PointType, PolygonType, WkbType, WktType,
11+
};
312

13+
/// A factory for creating GeoArrow extension types in Polars.
414
pub struct GeoArrowExtensionTypeFactory;
515

616
impl ExtensionTypeFactory for GeoArrowExtensionTypeFactory {
@@ -10,6 +20,55 @@ impl ExtensionTypeFactory for GeoArrowExtensionTypeFactory {
1020
storage: &DataType,
1121
metadata: Option<&str>,
1222
) -> Box<dyn ExtensionTypeImpl> {
13-
todo!()
23+
let arrow_data_type = polars_storage_type_to_arrow_data_type(storage);
24+
25+
// Create Arrow field with extension metadata
26+
let mut arrow_metadata = HashMap::<String, String>::with_capacity(2);
27+
arrow_metadata.insert(
28+
arrow_schema::extension::EXTENSION_TYPE_NAME_KEY.to_string(),
29+
name.to_string(),
30+
);
31+
if let Some(metadata) = metadata {
32+
arrow_metadata.insert(
33+
arrow_schema::extension::EXTENSION_TYPE_METADATA_KEY.to_string(),
34+
metadata.to_string(),
35+
);
36+
}
37+
38+
let arrow_field =
39+
arrow_schema::Field::new("", arrow_data_type, true).with_metadata(arrow_metadata);
40+
41+
// TODO: are we assured that the name matches the type here?
42+
// What do we do if the storage type isn't compatible with the extension type?
43+
let geoarrow_type = GeoArrowType::from_extension_field(&arrow_field)
44+
.expect("Creation of GeoArrow extension type");
45+
46+
match geoarrow_type {
47+
GeoArrowType::Point(t) => Box::new(PointType::new(t)),
48+
GeoArrowType::LineString(t) => Box::new(LineStringType::new(t)),
49+
GeoArrowType::Polygon(t) => Box::new(PolygonType::new(t)),
50+
GeoArrowType::MultiPoint(t) => Box::new(MultiPointType::new(t)),
51+
GeoArrowType::MultiLineString(t) => Box::new(MultiLineStringType::new(t)),
52+
GeoArrowType::MultiPolygon(t) => Box::new(MultiPolygonType::new(t)),
53+
GeoArrowType::GeometryCollection(t) => Box::new(GeometryCollectionType::new(t)),
54+
GeoArrowType::Geometry(t) => Box::new(GeometryType::new(t)),
55+
GeoArrowType::Rect(t) => Box::new(BoxType::new(t)),
56+
GeoArrowType::Wkb(t) => Box::new(WkbType::new(t)),
57+
GeoArrowType::LargeWkb(t) => Box::new(WkbType::new(t)),
58+
GeoArrowType::WkbView(t) => Box::new(WkbType::new(t)),
59+
GeoArrowType::Wkt(t) => Box::new(WktType::new(t)),
60+
GeoArrowType::LargeWkt(t) => Box::new(WktType::new(t)),
61+
GeoArrowType::WktView(t) => Box::new(WktType::new(t)),
62+
}
1463
}
1564
}
65+
66+
fn polars_storage_type_to_arrow_data_type(storage: &DataType) -> arrow_schema::DataType {
67+
let polars_field = polars_arrow::datatypes::Field::new(
68+
"".into(),
69+
storage.to_arrow(CompatLevel::newest()),
70+
true,
71+
);
72+
let arrow_field_from_ffi = polars_field_to_arrow(&polars_field);
73+
arrow_field_from_ffi.data_type().clone()
74+
}

geopolars/geopolars-extension/src/geoarrow.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
//! Definitions of GeoArrow extension types for the Polars extension registry.
2+
//!
3+
//! Each of the types contained in this module is a thin wrapper around the corresponding type in
4+
//! [`geoarrow_schema`] to implement Polars' [`ExtensionTypeImpl`].
5+
16
use std::any::Any;
27
use std::borrow::Cow;
38
use std::hash::{BuildHasher, Hash};
Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,39 @@
1-
mod factory;
2-
mod geoarrow;
1+
pub mod factory;
2+
pub mod geoarrow;
33

4+
use std::sync::Arc;
5+
6+
use arrow_schema::extension::ExtensionType;
7+
use polars::error::PolarsResult;
48
use polars_core::datatypes::extension::register_extension_type;
59

6-
pub fn register_all_extensions() {}
10+
use crate::factory::GeoArrowExtensionTypeFactory;
11+
12+
/// Register all GeoArrow extension types into the Polars extension registry.
13+
pub fn register_all_extensions() -> PolarsResult<()> {
14+
let factory = Arc::new(GeoArrowExtensionTypeFactory);
15+
16+
register_extension_type(geoarrow_schema::PointType::NAME, Some(factory.clone()))?;
17+
register_extension_type(geoarrow_schema::LineStringType::NAME, Some(factory.clone()))?;
18+
register_extension_type(geoarrow_schema::PolygonType::NAME, Some(factory.clone()))?;
19+
register_extension_type(geoarrow_schema::MultiPointType::NAME, Some(factory.clone()))?;
20+
register_extension_type(
21+
geoarrow_schema::MultiLineStringType::NAME,
22+
Some(factory.clone()),
23+
)?;
24+
register_extension_type(
25+
geoarrow_schema::MultiPolygonType::NAME,
26+
Some(factory.clone()),
27+
)?;
28+
register_extension_type(
29+
geoarrow_schema::GeometryCollectionType::NAME,
30+
Some(factory.clone()),
31+
)?;
32+
register_extension_type(geoarrow_schema::GeometryType::NAME, Some(factory.clone()))?;
33+
register_extension_type(geoarrow_schema::BoxType::NAME, Some(factory.clone()))?;
34+
35+
register_extension_type(geoarrow_schema::WkbType::NAME, Some(factory.clone()))?;
36+
register_extension_type(geoarrow_schema::WktType::NAME, Some(factory))?;
37+
38+
Ok(())
39+
}

0 commit comments

Comments
 (0)