From eb9b5a74086a72af1920d43f65705e655544db5f Mon Sep 17 00:00:00 2001 From: Gaurav Atreya Date: Thu, 28 Nov 2024 13:30:50 -0500 Subject: [PATCH] Add `Dataset::has_capability` for dataset capabilities test --- src/dataset.rs | 50 +++++++++++++++++++++++++++++++++++++++++++-- src/vector/layer.rs | 2 +- 2 files changed, 49 insertions(+), 3 deletions(-) diff --git a/src/dataset.rs b/src/dataset.rs index 280edd6c..970253d3 100644 --- a/src/dataset.rs +++ b/src/dataset.rs @@ -1,4 +1,9 @@ -use std::{ffi::CString, ffi::NulError, path::Path, ptr}; +use std::{ + ffi::NulError, + ffi::{CStr, CString}, + path::Path, + ptr, +}; use gdal_sys::{CPLErr, GDALDatasetH, GDALMajorObjectH}; @@ -11,6 +16,29 @@ use crate::{ gdal_major_object::MajorObject, spatial_ref::SpatialRef, Driver, GeoTransform, Metadata, }; +pub struct DatasetCapability(&'static CStr); + +/// Dataset capabilities +impl DatasetCapability { + /// datasource can create new layers + pub const CREATE_LAYER: DatasetCapability = DatasetCapability(c"CreateLayer"); + /// datasource can delete existing layers + pub const DELETE_LAYER: DatasetCapability = DatasetCapability(c"DeleteLayer"); + /// layers of this datasource support CreateGeomField() just after layer creation + pub const CREATE_GEOM_FIELD_AFTER_CREATE_LAYER: DatasetCapability = + DatasetCapability(c"CreateGeomFieldAfterCreateLayer"); + /// datasource supports curve geometries + pub const CURVE_GEOMETRIES: DatasetCapability = DatasetCapability(c"CurveGeometries"); + /// datasource supports (efficient) transactions + pub const TRANSACTIONS: DatasetCapability = DatasetCapability(c"Transactions"); + /// datasource supports transactions through emulation + pub const EMULATED_TRANSACTIONS: DatasetCapability = DatasetCapability(c"EmulatedTransactions"); + /// datasource has a dedicated GetNextFeature() implementation, potentially returning features from layers in a non sequential way + pub const RANDOM_LAYER_READ: DatasetCapability = DatasetCapability(c"RandomLayerRead"); + /// datasource supports calling CreateFeature() on layers in a non sequential way + pub const RANDOM_LAYER_WRITE: DatasetCapability = DatasetCapability(c"RandomLayerWrite"); +} + /// Wrapper around a [`GDALDataset`][GDALDataset] object. /// /// Represents both a [vector dataset][vector-data-model] @@ -327,6 +355,10 @@ impl Dataset { } Ok(transformation) } + + pub fn has_capability(&self, capability: DatasetCapability) -> bool { + unsafe { gdal_sys::GDALDatasetTestCapability(self.c_dataset(), capability.0.as_ptr()) == 1 } + } } impl MajorObject for Dataset { @@ -351,7 +383,8 @@ impl Drop for Dataset { mod tests { use gdal_sys::GDALAccess; - use crate::test_utils::fixture; + use crate::dataset::DatasetCapability; + use crate::test_utils::{fixture, open_gpkg_for_update}; use crate::GdalOpenFlags; use super::*; @@ -446,6 +479,19 @@ mod tests { .unwrap_err(); } + #[test] + fn test_dataset_capabilities() { + let ds = Dataset::open(fixture("poly.gpkg")).unwrap(); + assert!(!ds.has_capability(DatasetCapability::CREATE_LAYER)); + assert!(!ds.has_capability(DatasetCapability::DELETE_LAYER)); + assert!(ds.has_capability(DatasetCapability::TRANSACTIONS)); + + let (_tmp_path, ds) = open_gpkg_for_update(&fixture("poly.gpkg")); + assert!(ds.has_capability(DatasetCapability::CREATE_LAYER)); + assert!(ds.has_capability(DatasetCapability::DELETE_LAYER)); + assert!(ds.has_capability(DatasetCapability::TRANSACTIONS)); + } + #[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 826e4372..456f031e 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,