Skip to content

Commit

Permalink
Merge #324
Browse files Browse the repository at this point in the history
324: add a driver manager wrapper r=jdroenner a=ChristianBeilschmidt

- [X] I agree to follow the project's [code of conduct](https://github.com/georust/gdal/blob/master/CODE_OF_CONDUCT.md).
- [x] I added an entry to `CHANGES.md` if knowledge of this change could be valuable to users.
---

I added a wrapper for the `DriverManager.`
I moved some methods to this struct's impl and deprecated them in the `Driver`.
Moreover, I created integration tests that use the manager. They would interfere with other tests.

Co-authored-by: Christian Beilschmidt <[email protected]>
  • Loading branch information
bors[bot] and ChristianBeilschmidt authored Oct 31, 2022
2 parents f25c391 + 141c8d8 commit 2ba3db2
Show file tree
Hide file tree
Showing 12 changed files with 293 additions and 68 deletions.
10 changes: 7 additions & 3 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,19 @@

- <https://github.com/georust/gdal/pull/308>

- Added quality-of-life features to `CslStringList`: `len`, `is_empty`, `Debug` and `Iterator` implementations.
- Added quality-of-life features to `CslStringList`: `len`, `is_empty`, `Debug` and `Iterator` implementations.

- <https://github.com/georust/gdal/pull/311>

- Added ability to set color table for bands with palette color interpretation.
- Added ability to set color table for bands with palette color interpretation.
Added ability to create a color ramp (interpolated) color table.

- <https://github.com/georust/gdal/pull/314>

- Added a wrapper for the `DriverManager`

- <https://github.com/georust/gdal/pull/324>

## 0.13

- Add prebuild bindings for GDAL 3.5
Expand Down Expand Up @@ -110,7 +114,7 @@

- Added `Geometry::to_geo` method for GDAL to geo-types Geometry conversions.

- <https://github.com/georust/gdal/pull/295>
- <https://github.com/georust/gdal/pull/295>

- Add `Rasterband::set_scale` and `Rasterband::set_offset` methods

Expand Down
2 changes: 1 addition & 1 deletion examples/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ fn main() {
use gdal::{Dataset, Metadata};
use std::path::Path;

let driver = gdal::Driver::get_by_name("mem").unwrap();
let driver = gdal::DriverManager::get_driver_by_name("mem").unwrap();
println!("driver description: {:?}", driver.description());

let path = Path::new("./fixtures/tinymarble.png");
Expand Down
6 changes: 3 additions & 3 deletions examples/read_write_ogr.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use gdal::errors::Result;
use gdal::spatial_ref::{CoordTransform, SpatialRef};
use gdal::vector::*;
use gdal::{Dataset, Driver};
use gdal::Dataset;
use gdal::{vector::*, DriverManager};
use std::fs;
use std::path::Path;

Expand All @@ -17,7 +17,7 @@ fn run() -> Result<()> {
// Create a new dataset:
let path = std::env::temp_dir().join("abcde.shp");
let _ = fs::remove_file(&path);
let drv = Driver::get_by_name("ESRI Shapefile")?;
let drv = DriverManager::get_driver_by_name("ESRI Shapefile")?;
let mut ds = drv.create_vector_only(path.to_str().unwrap())?;
let lyr = ds.create_layer(Default::default())?;

Expand Down
6 changes: 3 additions & 3 deletions examples/read_write_ogr_datetime.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use gdal::vector::LayerAccess;
use gdal::{vector::LayerAccess, DriverManager};

fn run() -> gdal::errors::Result<()> {
use chrono::Duration;
use gdal::vector::{Defn, Feature, FieldDefn, FieldValue};
use gdal::{Dataset, Driver};
use gdal::Dataset;
use std::ops::Add;
use std::path::Path;

Expand All @@ -15,7 +15,7 @@ fn run() -> gdal::errors::Result<()> {
// Create a new dataset:
let path = std::env::temp_dir().join("later.geojson");
let _ = std::fs::remove_file(&path);
let drv = Driver::get_by_name("GeoJSON")?;
let drv = DriverManager::get_driver_by_name("GeoJSON")?;
let mut ds = drv.create_vector_only(path.to_str().unwrap())?;
let lyr = ds.create_layer(Default::default())?;

Expand Down
6 changes: 3 additions & 3 deletions examples/write_ogr.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
use gdal::errors::Result;
use gdal::vector::{Defn, Feature, FieldDefn, FieldValue, Geometry, LayerAccess, OGRFieldType};
use gdal::Driver;
use gdal::DriverManager;
use std::fs;

/// Example 1, the detailed way:
fn example_1() -> Result<()> {
let path = std::env::temp_dir().join("output1.geojson");
let _ = fs::remove_file(&path);
let drv = Driver::get_by_name("GeoJSON")?;
let drv = DriverManager::get_driver_by_name("GeoJSON")?;
let mut ds = drv.create_vector_only(path.to_str().unwrap())?;

let lyr = ds.create_layer(Default::default())?;
Expand Down Expand Up @@ -52,7 +52,7 @@ fn example_1() -> Result<()> {
fn example_2() -> Result<()> {
let path = std::env::temp_dir().join("output2.geojson");
let _ = fs::remove_file(&path);
let driver = Driver::get_by_name("GeoJSON")?;
let driver = DriverManager::get_driver_by_name("GeoJSON")?;
let mut ds = driver.create_vector_only(path.to_str().unwrap())?;
let mut layer = ds.create_layer(Default::default())?;

Expand Down
185 changes: 158 additions & 27 deletions src/driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,7 @@ use crate::errors::*;
static START: Once = Once::new();

pub fn _register_drivers() {
unsafe {
START.call_once(|| {
gdal_sys::GDALAllRegister();
});
}
START.call_once(DriverManager::register_all);
}

/// # Raster and Vector Driver API
Expand Down Expand Up @@ -63,14 +59,9 @@ impl Driver {
/// ```text
/// Cloud optimized GeoTIFF generator
/// ```
#[deprecated(note = "Please use `DriverManager::get_driver_by_name()` instead")]
pub fn get_by_name(name: &str) -> Result<Driver> {
_register_drivers();
let c_name = CString::new(name)?;
let c_driver = unsafe { gdal_sys::GDALGetDriverByName(c_name.as_ptr()) };
if c_driver.is_null() {
return Err(_last_null_pointer_err("GDALGetDriverByName"));
};
Ok(Driver { c_driver })
DriverManager::get_driver_by_name(name)
}

/// Returns the driver with the given index, which must be less than the value returned by
Expand All @@ -92,13 +83,9 @@ impl Driver {
/// ```text
/// 'VRT' is 'Virtual Raster'
/// ```
#[deprecated(note = "Please use `DriverManager::get_driver()` instead")]
pub fn get(index: usize) -> Result<Driver> {
_register_drivers();
let c_driver = unsafe { gdal_sys::GDALGetDriver(index.try_into().unwrap()) };
if c_driver.is_null() {
return Err(_last_null_pointer_err("GDALGetDriver"));
}
Ok(Driver { c_driver })
DriverManager::get_driver(index)
}

/// Returns the number of registered drivers.
Expand All @@ -112,10 +99,9 @@ impl Driver {
/// ```text
/// 203 drivers are registered
/// ```
#[deprecated(note = "Please use `DriverManager::count()` instead")]
pub fn count() -> usize {
_register_drivers();
let count = unsafe { gdal_sys::GDALGetDriverCount() };
count.try_into().unwrap()
DriverManager::count()
}

/// Return the short name of a driver.
Expand Down Expand Up @@ -149,9 +135,9 @@ impl Driver {
///
/// ```rust, no_run
/// # fn main() -> gdal::errors::Result<()> {
/// use gdal::Driver;
/// use gdal::DriverManager;
/// use gdal::raster::GdalType;
/// let d = Driver::get_by_name("MEM")?;
/// let d = DriverManager::get_driver_by_name("MEM")?;
/// let ds = d.create("in-memory", 64, 64, 3)?;
/// assert_eq!(ds.raster_count(), 3);
/// assert_eq!(ds.raster_size(), (64, 64));
Expand All @@ -178,9 +164,9 @@ impl Driver {
///
/// ```rust, no_run
/// # fn main() -> gdal::errors::Result<()> {
/// use gdal::Driver;
/// use gdal::DriverManager;
/// use gdal::raster::GdalType;
/// let d = Driver::get_by_name("MEM")?;
/// let d = DriverManager::get_driver_by_name("MEM")?;
/// let ds = d.create_with_band_type::<f64, _>("in-memory", 64, 64, 3)?;
/// assert_eq!(ds.raster_count(), 3);
/// assert_eq!(ds.raster_size(), (64, 64));
Expand Down Expand Up @@ -210,11 +196,11 @@ impl Driver {
///
/// ```rust, no_run
/// # fn main() -> gdal::errors::Result<()> {
/// use gdal::Driver;
/// use gdal::DriverManager;
/// use gdal::raster::RasterCreationOption;
/// use gdal::raster::GdalType;
/// use gdal::spatial_ref::SpatialRef;
/// let d = Driver::get_by_name("BMP")?;
/// let d = DriverManager::get_driver_by_name("BMP")?;
/// let options = [
/// RasterCreationOption {
/// key: "WORLDFILE",
Expand Down Expand Up @@ -366,3 +352,148 @@ impl MajorObject for Driver {
}

impl Metadata for Driver {}

/// A wrapper around `GDALDriverManager`.
/// This struct helps listing and registering [`Driver`]s.
pub struct DriverManager;

impl DriverManager {
/// Returns the number of registered drivers.
///
/// # Example
///
/// ```rust, no_run
/// use gdal::DriverManager;
/// println!("{} drivers are registered", DriverManager::count());
/// ```
/// ```text
/// 203 drivers are registered
/// ```
pub fn count() -> usize {
_register_drivers();
let count = unsafe { gdal_sys::GDALGetDriverCount() };
count
.try_into()
.expect("The returned count should be zero or positive")
}

/// Returns the driver with the given index, which must be less than the value returned by
/// `DriverManager::count()`.
///
/// See also: [`count`](Self::count)
///
/// # Example
///
/// ```rust, no_run
/// use gdal::DriverManager;
/// # fn main() -> gdal::errors::Result<()> {
/// assert!(DriverManager::count() > 0);
/// let d = DriverManager::get_driver(0)?;
/// println!("'{}' is '{}'", d.short_name(), d.long_name());
/// # Ok(())
/// # }
/// ```
/// ```text
/// 'VRT' is 'Virtual Raster'
/// ```
pub fn get_driver(index: usize) -> Result<Driver> {
_register_drivers();
let c_driver = unsafe { gdal_sys::GDALGetDriver(index.try_into().unwrap()) };
if c_driver.is_null() {
// `GDALGetDriver` just returns `null` and sets no error message
return Err(GdalError::NullPointer {
method_name: "GDALGetDriver",
msg: "Unable to find driver".to_string(),
});
}
Ok(Driver { c_driver })
}

/// Returns the driver with the given short name or [`Err`] if not found.
///
/// See also: [`count`](Self::count), [`get`](Self::get)
///
/// # Example
///
/// ```rust, no_run
/// use gdal::DriverManager;
/// # fn main() -> gdal::errors::Result<()> {
/// let cog_driver = DriverManager::get_driver_by_name("COG")?;
/// println!("{}", cog_driver.long_name());
/// # Ok(())
/// # }
/// ```
/// ```text
/// Cloud optimized GeoTIFF generator
/// ```
pub fn get_driver_by_name(name: &str) -> Result<Driver> {
_register_drivers();
let c_name = CString::new(name)?;
let c_driver = unsafe { gdal_sys::GDALGetDriverByName(c_name.as_ptr()) };
if c_driver.is_null() {
// `GDALGetDriverByName` just returns `null` and sets no error message
return Err(GdalError::NullPointer {
method_name: "GDALGetDriverByName",
msg: "Unable to find driver".to_string(),
});
};
Ok(Driver { c_driver })
}

/// Register a driver for use.
///
/// Wraps [`GDALRegisterDriver()`](https://gdal.org/api/raster_c_api.html#_CPPv418GDALRegisterDriver11GDALDriverH)
pub fn register_driver(driver: &Driver) -> usize {
let index = unsafe { gdal_sys::GDALRegisterDriver(driver.c_driver) };
index
.try_into()
.expect("The returned index should be zero or positive")
}

/// Deregister the passed driver.
///
/// Wraps [`GDALDeregisterDriver()`](https://gdal.org/api/raster_c_api.html#_CPPv420GDALDeregisterDriver11GDALDriverH)
pub fn deregister_driver(driver: &Driver) {
unsafe {
gdal_sys::GDALDeregisterDriver(driver.c_driver);
}
}

/// Register all known GDAL drivers.
///
/// Wraps [`GDALAllRegister()`](https://gdal.org/api/raster_c_api.html#gdal_8h_1a9d40bc998bd6ed07ccde96028e85ae26)
pub fn register_all() {
unsafe {
gdal_sys::GDALAllRegister();
}
}

/// Prevents the automatic registration of all known GDAL drivers when first calling create, open, etc.
pub fn prevent_auto_registration() {
START.call_once(|| {});
}

/// Destroys the driver manager, i.e., unloads all drivers.
///
/// Wraps [`GDALDestroyDriverManager()`](https://gdal.org/api/raster_c_api.html#_CPPv417GDALDestroyDriver11GDALDriverH)
pub fn destroy() {
unsafe {
gdal_sys::GDALDestroyDriverManager();
}
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_driver_access() {
let driver = DriverManager::get_driver_by_name("GTiff").unwrap();
assert_eq!(driver.short_name(), "GTiff");
assert_eq!(driver.long_name(), "GeoTIFF");

assert!(DriverManager::count() > 0);
assert!(DriverManager::get_driver(0).is_ok());
}
}
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ pub use dataset::{
Dataset, DatasetOptions, GdalOpenFlags, GeoTransform, GeoTransformEx, LayerIterator,
LayerOptions, Transaction,
};
pub use driver::Driver;
pub use driver::{Driver, DriverManager};
pub use metadata::Metadata;

#[cfg(test)]
Expand Down
4 changes: 2 additions & 2 deletions src/programs/raster/mdimtranslate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ mod tests {

use super::*;

use crate::{DatasetOptions, Driver, GdalOpenFlags};
use crate::{DatasetOptions, DriverManager, GdalOpenFlags};

#[test]
#[cfg_attr(not(all(major_ge_3, minor_ge_4)), ignore)]
Expand Down Expand Up @@ -277,7 +277,7 @@ mod tests {
};
let dataset = Dataset::open_ex(fixture, dataset_options).unwrap();

let driver = Driver::get_by_name("MEM").unwrap();
let driver = DriverManager::get_driver_by_name("MEM").unwrap();
let output_dataset = driver.create("", 5, 7, 1).unwrap();

let error = multi_dim_translate(
Expand Down
Loading

0 comments on commit 2ba3db2

Please sign in to comment.