Skip to content

feat(sedona-gdal): add convenience facade and mem builder#697

Open
Kontinuation wants to merge 13 commits intoapache:mainfrom
Kontinuation:feat/sedona-gdal-safe-facade
Open

feat(sedona-gdal): add convenience facade and mem builder#697
Kontinuation wants to merge 13 commits intoapache:mainfrom
Kontinuation:feat/sedona-gdal-safe-facade

Conversation

@Kontinuation
Copy link
Copy Markdown
Member

@Kontinuation Kontinuation commented Mar 9, 2026

Summary

  • add the high-level Gdal facade and with_global_gdal convenience entry point
  • add the MEM dataset builder on top of the lower-level dataset and raster wrappers
  • keep the top-level API explicit by importing concrete raster/vector modules instead of relying on wrapper re-export aliases

Depends on #698.

Testing

  • cargo test -p sedona-gdal
  • cargo clippy -p sedona-gdal -- -D warnings

@Kontinuation Kontinuation force-pushed the feat/sedona-gdal-safe-facade branch 6 times, most recently from e7e3be7 to 98cbbd2 Compare March 13, 2026 06:38
@Kontinuation Kontinuation force-pushed the feat/sedona-gdal-safe-facade branch 2 times, most recently from 4008bc8 to 006695f Compare March 26, 2026 14:37
@Kontinuation Kontinuation force-pushed the feat/sedona-gdal-safe-facade branch from 006695f to 43b3ba5 Compare April 1, 2026 05:10
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a higher-level ergonomics layer for sedona-gdal by adding a Gdal facade and a fluent MEM dataset builder, while keeping the lower-level API available for explicit use.

Changes:

  • Add Gdal high-level facade wrapping &'static GdalApi to reduce explicit api plumbing at call sites.
  • Add MemDatasetBuilder for constructing MEM datasets (including zero-copy band attachment plus optional geotransform/projection/nodata).
  • Export call_gdal_api! as a macro and add with_global_gdal convenience entry point.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
c/sedona-gdal/src/mem.rs New MEM dataset builder and MEM dataset creation helper + tests.
c/sedona-gdal/src/lib.rs Exposes the new gdal and mem modules publicly.
c/sedona-gdal/src/global.rs Adds with_global_gdal convenience wrapper around the global API handle.
c/sedona-gdal/src/gdal.rs New Gdal facade providing ergonomic wrappers for common operations.
c/sedona-gdal/src/gdal_api.rs Exports call_gdal_api! macro (now public/root-exported).
Comments suppressed due to low confidence (1)

c/sedona-gdal/src/gdal_api.rs:48

  • call_gdal_api is now marked #[macro_export], which makes it part of the public API and exports it at the crate root. However, the macro expands to $api.inner.$func, and inner is pub(crate), so downstream crates cannot actually use the exported macro (privacy check will fail). Consider removing #[macro_export] and keeping it crate-internal (the existing pub(crate) use call_gdal_api; already enables use across this crate without widening the public surface).
#[macro_export]
macro_rules! call_gdal_api {
    ($api:expr, $func:ident $(, $arg:expr)*) => {
        if let Some(func) = $api.inner.$func {
            func($($arg),*)
        } else {
            panic!("{} function not available", stringify!($func))
        }
    };
}

pub(crate) use call_gdal_api;


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@Kontinuation Kontinuation marked this pull request as ready for review April 1, 2026 06:49
Copy link
Copy Markdown
Member

@paleolimbot paleolimbot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few optional things that may be worth considering. Thank you!

Comment on lines +138 to +161
/// Add a zero-copy band with custom offsets and optional nodata.
///
/// # Safety
///
/// The caller must ensure `data_ptr` points to a valid buffer of sufficient size
/// for the given dimensions and offsets, is properly aligned for `data_type`, and
/// outlives the built [`Dataset`].
pub unsafe fn add_band_with_options(
mut self,
data_type: GdalDataType,
data_ptr: *mut u8,
pixel_offset: Option<i64>,
line_offset: Option<i64>,
nodata: Option<Nodata>,
) -> Self {
self.bands.push(MemBand {
data_type,
data_ptr,
pixel_offset,
line_offset,
nodata,
});
self
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is so cool

Comment on lines +66 to +67
/// Fetch GDAL version information for a standard request key.
pub fn version_info(&self, request: &str) -> String {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are all a bit light on the documentation (maybe they could link to the underlying implementation's docs which I seem to remember have a bit more depth?). Also OK to defer since this is mostly intended to be for internal usage.

Comment on lines +45 to +53
/// High-level convenience wrapper around [`GdalApi`].
///
/// Stores a `&'static GdalApi` reference and provides ergonomic methods that
/// delegate to the various constructors and free functions in the crate.
pub struct Gdal {
api: &'static GdalApi,
}

impl Gdal {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do like the idea of a high-level object that dishes out other safe high-level objects, although putting it all here involves repeating some documentation (or omitting it) and I'm not sure it's needed given that the constructors it refers to are pub anyway. Reexporting the structs or functions that are part of the intended external API might be another way to expose the API without loosing the docs?

Comment on lines +169 to +171
/// Set the dataset projection definition string.
pub fn projection(mut self, wkt: impl Into<String>) -> Self {
self.projection = Some(wkt.into());
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this actually WKT or can this by anything? (It may be less error prone to accept anything or an explicit spatialref object)

Comment on lines +303 to +307
/// `data_ptr` must point to valid mutable band data that outlives this dataset.
pub unsafe fn add_band_with_data(
&self,
data_type: RustGdalDataType,
data_ptr: *const u8,
data_ptr: *mut u8,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this actually required to be mutable? (This seems like a strange constraint, and also one that will result in it not being particularly useful to us)

Comment on lines +134 to +136
pub unsafe fn add_band(self, data_type: GdalDataType, data_ptr: *mut u8) -> Self {
self.add_band_with_options(data_type, data_ptr, None, None, None)
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you sure the data pointer has to be mutable? (This would preclude backing a GDAL mem dataset with Arrow data?)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants