From 262c9fe55e0a0e2df2b52340db4084b6082ddcc2 Mon Sep 17 00:00:00 2001 From: Gaurav Atreya Date: Thu, 28 Nov 2024 09:27:54 -0500 Subject: [PATCH] Add `Dataset::has_capability` for dataset capabilities test --- src/dataset.rs | 63 ++++++++++++++++++++++++++++++++++++++++++++- src/vector/layer.rs | 2 +- 2 files changed, 63 insertions(+), 2 deletions(-) diff --git a/src/dataset.rs b/src/dataset.rs index 280edd6c9..597325a11 100644 --- a/src/dataset.rs +++ b/src/dataset.rs @@ -11,6 +11,44 @@ use crate::{ gdal_major_object::MajorObject, spatial_ref::SpatialRef, Driver, GeoTransform, Metadata, }; +/// Dataset capabilities +#[allow(clippy::enum_variant_names)] +pub enum DatasetCaps { + /// datasource can create new layers + ODsCCreateLayer, + /// datasource can delete existing layers + ODsCDeleteLayer, + /// layers of this datasource support CreateGeomField() just after layer creation + ODsCCreateGeomFieldAfterCreateLayer, + /// datasource supports curve geometries + ODsCCurveGeometries, + /// datasource supports (efficient) transactions + ODsCTransactions, + /// datasource supports transactions through emulation + ODsCEmulatedTransactions, + /// datasource has a dedicated GetNextFeature() implementation, potentially returning features from layers in a non sequential way + ODsCRandomLayerRead, + /// datasource supports calling CreateFeature() on layers in a non sequential way + ODsCRandomLayerWrite, +} + +// Manage conversion to Gdal values +impl DatasetCaps { + fn into_cstring(self) -> CString { + CString::new(match self { + Self::ODsCCreateLayer => "CreateLayer", + Self::ODsCDeleteLayer => "DeleteLayer", + Self::ODsCCreateGeomFieldAfterCreateLayer => "CreateGeomFieldAfterCreateLayer", + Self::ODsCCurveGeometries => "CurveGeometries", + Self::ODsCTransactions => "Transactions", + Self::ODsCEmulatedTransactions => "EmulatedTransactions", + Self::ODsCRandomLayerRead => "RandomLayerRead", + Self::ODsCRandomLayerWrite => "RandomLayerWrite", + }) + .unwrap() + } +} + /// Wrapper around a [`GDALDataset`][GDALDataset] object. /// /// Represents both a [vector dataset][vector-data-model] @@ -327,6 +365,15 @@ impl Dataset { } Ok(transformation) } + + pub fn has_capability(&self, capability: DatasetCaps) -> bool { + unsafe { + gdal_sys::GDALDatasetTestCapability( + self.c_dataset(), + capability.into_cstring().as_ptr(), + ) == 1 + } + } } impl MajorObject for Dataset { @@ -351,7 +398,8 @@ impl Drop for Dataset { mod tests { use gdal_sys::GDALAccess; - use crate::test_utils::fixture; + use crate::dataset::DatasetCaps::*; + use crate::test_utils::{fixture, open_gpkg_for_update}; use crate::GdalOpenFlags; use super::*; @@ -446,6 +494,19 @@ mod tests { .unwrap_err(); } + #[test] + fn test_dataset_capabilities() { + let ds = Dataset::open(fixture("poly.gpkg")).unwrap(); + assert!(!ds.has_capability(ODsCCreateLayer)); + assert!(!ds.has_capability(ODsCDeleteLayer)); + assert!(ds.has_capability(ODsCTransactions)); + + let (_tmp_path, ds) = open_gpkg_for_update(&fixture("poly.gpkg")); + assert!(ds.has_capability(ODsCCreateLayer)); + assert!(ds.has_capability(ODsCDeleteLayer)); + assert!(ds.has_capability(ODsCTransactions)); + } + #[test] fn test_raster_count_on_vector() { let ds = Dataset::open(fixture("roads.geojson")).unwrap(); diff --git a/src/vector/layer.rs b/src/vector/layer.rs index 826e43720..456f031e0 100644 --- a/src/vector/layer.rs +++ b/src/vector/layer.rs @@ -41,7 +41,7 @@ pub enum LayerCaps { OLCAlterFieldDefn, /// Layer capability for transactions OLCTransactions, - /// Layer capability for feature deletiond + /// Layer capability for feature deletion OLCDeleteFeature, /// Layer capability for setting next feature index OLCFastSetNextByIndex,