From 2d87bca9bdadfb7646481f9cca21b2adfcd15095 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20Dr=C3=B6nner?= Date: Mon, 16 May 2016 16:40:11 +0200 Subject: [PATCH 1/3] first version of metadata handling --- examples/metadata.rs | 15 +++++++++++++++ src/gdal_major_object.rs | 5 +++++ src/lib.rs | 3 +++ src/metadata.rs | 41 ++++++++++++++++++++++++++++++++++++++++ src/raster/dataset.rs | 10 ++++++++++ src/raster/tests.rs | 17 +++++++++++++++++ src/vector/dataset.rs | 10 ++++++++++ src/vector/layer.rs | 10 ++++++++++ 8 files changed, 111 insertions(+) create mode 100644 examples/metadata.rs create mode 100644 src/gdal_major_object.rs create mode 100644 src/metadata.rs diff --git a/examples/metadata.rs b/examples/metadata.rs new file mode 100644 index 00000000..117ceee8 --- /dev/null +++ b/examples/metadata.rs @@ -0,0 +1,15 @@ +extern crate gdal; + +fn main() { + use std::path::Path; + use gdal::raster::dataset::Dataset; + use gdal::metadata::Metadata; + + let path = Path::new("./fixtures/tinymarble.png"); + let dataset = Dataset::open(path).unwrap(); + let key = "INTERLEAVE"; + let domain = "IMAGE_STRUCTURE"; + let meta = dataset.get_metadata_item(key, domain); + println!("domain: {:?} key: {:?} -> value: {:?}", domain, key, meta); + +} diff --git a/src/gdal_major_object.rs b/src/gdal_major_object.rs new file mode 100644 index 00000000..c59b99da --- /dev/null +++ b/src/gdal_major_object.rs @@ -0,0 +1,5 @@ +use libc::{c_void}; + +pub trait MajorObject { + unsafe fn get_gdal_object_ptr(&self) -> *const c_void; +} diff --git a/src/lib.rs b/src/lib.rs index 65c3cece..9c5dcbf8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -20,12 +20,15 @@ #![crate_name="gdal"] #![crate_type="lib"] + extern crate libc; extern crate geo; pub use version::version_info; mod utils; +mod gdal_major_object; +pub mod metadata; pub mod version; pub mod raster; pub mod vector; diff --git a/src/metadata.rs b/src/metadata.rs new file mode 100644 index 00000000..23c370e1 --- /dev/null +++ b/src/metadata.rs @@ -0,0 +1,41 @@ +use libc::{c_char, c_void, c_int}; +use utils::{_string}; +use std::ffi::{CString}; +use gdal_major_object::MajorObject; + +#[link(name="gdal")] +extern { + fn GDALGetMetadataItem(hGdalMayorObject: *const c_void, pszName: *const c_char, pszDomain: *const c_char) -> *const c_char; + fn GDALSetMetadataItem(hGdalMayorObject: *const c_void, pszName: *const c_char, pszValue: *const c_char, pszDomain: *const c_char ) -> c_int; +} + +pub trait Metadata: MajorObject { + + fn get_metadata_item(&self, key: &str, domain: &str) -> Option { + let c_key = CString::new(key.to_owned()).expect("Could not transform String to CString"); // FIXME: no unwrap + let c_domain = CString::new(domain.to_owned()).expect("Could not transform String to CString"); + + let c_res = unsafe { GDALGetMetadataItem(self.get_gdal_object_ptr(), c_key.as_ptr(), c_domain.as_ptr())}; + if c_res.is_null() { + None + } + else { + Some(_string(c_res)) + } + } + + fn set_metadata_item(&mut self, key: &str, value: &str, domain: &str) -> Result<(), ()> { + let c_key = CString::new(key.to_owned()).expect("Could not transform String to CString"); // FIXME: no unwrap + let c_domain = CString::new(domain.to_owned()).expect("Could not transform String to CString"); + let c_value = CString::new(value.to_owned()).expect("Could not transform String to CString"); + + let c_res = unsafe { GDALSetMetadataItem(self.get_gdal_object_ptr(), c_key.as_ptr(), c_value.as_ptr(), c_domain.as_ptr())}; + if c_res == 0 { // TODO: convert into CPLErr? + Ok(()) + } + else { + Err(()) + } + } + +} diff --git a/src/raster/dataset.rs b/src/raster/dataset.rs index ded78ed3..8bb2f405 100644 --- a/src/raster/dataset.rs +++ b/src/raster/dataset.rs @@ -6,6 +6,8 @@ use raster::{gdal, Driver}; use raster::driver::_register_drivers; use raster::gdal_enums::{GDALRWFlag, GDALAccess, GDALDataType}; use raster::types::GdalType; +use gdal_major_object::MajorObject; +use metadata::Metadata; pub type GeoTransform = [c_double; 6]; @@ -13,6 +15,14 @@ pub struct Dataset { c_dataset: *const c_void, } +impl MajorObject for Dataset { + unsafe fn get_gdal_object_ptr(&self) -> *const c_void { + self.c_dataset + } +} + +impl Metadata for Dataset {} + impl Drop for Dataset { fn drop(&mut self) { diff --git a/src/raster/tests.rs b/src/raster/tests.rs index d17f0b20..da3130ea 100644 --- a/src/raster/tests.rs +++ b/src/raster/tests.rs @@ -113,6 +113,23 @@ fn test_get_dataset_driver() { assert_eq!(driver.long_name(), "Portable Network Graphics"); } +#[test] +fn test_get_metadata_item() { + + use metadata::Metadata; + + let dataset = Dataset::open(fixture!("tinymarble.png")).unwrap(); + let key = "None"; + let domain = "None"; + let meta = dataset.get_metadata_item(key, domain); + assert_eq!(meta, None); + + let key = "INTERLEAVE"; + let domain = "IMAGE_STRUCTURE"; + let meta = dataset.get_metadata_item(key, domain); + assert_eq!(meta, Some(String::from("PIXEL"))); +} + #[test] fn test_create() { diff --git a/src/vector/dataset.rs b/src/vector/dataset.rs index 50831f24..69724cb3 100644 --- a/src/vector/dataset.rs +++ b/src/vector/dataset.rs @@ -4,6 +4,8 @@ use std::ptr::null; use libc::{c_int, c_void}; use vector::{ogr, Layer}; use vector::driver::_register_drivers; +use gdal_major_object::MajorObject; +use metadata::Metadata; /// Vector dataset /// @@ -19,6 +21,14 @@ pub struct Dataset { layers: Vec, } +impl MajorObject for Dataset { + unsafe fn get_gdal_object_ptr(&self) -> *const c_void { + self.c_dataset + } +} + +impl Metadata for Dataset {} + impl Dataset { pub unsafe fn _with_c_dataset(c_dataset: *const c_void) -> Dataset { diff --git a/src/vector/layer.rs b/src/vector/layer.rs index 55d55e94..83c1e868 100644 --- a/src/vector/layer.rs +++ b/src/vector/layer.rs @@ -2,6 +2,8 @@ use std::ptr::null; use libc::{c_void}; use vector::{ogr, Feature, Geometry}; use vector::defn::Defn; +use gdal_major_object::MajorObject; +use metadata::Metadata; /// Layer in a vector dataset /// @@ -20,6 +22,14 @@ pub struct Layer { defn: Defn, } +impl MajorObject for Layer { + unsafe fn get_gdal_object_ptr(&self) -> *const c_void { + self.c_layer + } +} + +impl Metadata for Layer {} + impl Layer { pub unsafe fn _with_c_layer(c_layer: *const c_void) -> Layer { From 11b70c50c728bdf6f76332df56471de2f4728767 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20Dr=C3=B6nner?= Date: Thu, 26 May 2016 22:15:59 +0200 Subject: [PATCH 2/3] * remove .expect() from get_metadata_item and set_metadata_item. * added test for set_metadata_item --- src/metadata.rs | 37 ++++++++++++++++++------------------- src/raster/tests.rs | 17 +++++++++++++++++ 2 files changed, 35 insertions(+), 19 deletions(-) diff --git a/src/metadata.rs b/src/metadata.rs index 23c370e1..68eb9de8 100644 --- a/src/metadata.rs +++ b/src/metadata.rs @@ -12,30 +12,29 @@ extern { pub trait Metadata: MajorObject { fn get_metadata_item(&self, key: &str, domain: &str) -> Option { - let c_key = CString::new(key.to_owned()).expect("Could not transform String to CString"); // FIXME: no unwrap - let c_domain = CString::new(domain.to_owned()).expect("Could not transform String to CString"); - - let c_res = unsafe { GDALGetMetadataItem(self.get_gdal_object_ptr(), c_key.as_ptr(), c_domain.as_ptr())}; - if c_res.is_null() { - None - } - else { - Some(_string(c_res)) + if let Ok(c_key) = CString::new(key.to_owned()) { + if let Ok(c_domain) = CString::new(domain.to_owned()){ + let c_res = unsafe { GDALGetMetadataItem(self.get_gdal_object_ptr(), c_key.as_ptr(), c_domain.as_ptr())}; + if !c_res.is_null() { + return Some(_string(c_res)); + } + } } + None } fn set_metadata_item(&mut self, key: &str, value: &str, domain: &str) -> Result<(), ()> { - let c_key = CString::new(key.to_owned()).expect("Could not transform String to CString"); // FIXME: no unwrap - let c_domain = CString::new(domain.to_owned()).expect("Could not transform String to CString"); - let c_value = CString::new(value.to_owned()).expect("Could not transform String to CString"); - - let c_res = unsafe { GDALSetMetadataItem(self.get_gdal_object_ptr(), c_key.as_ptr(), c_value.as_ptr(), c_domain.as_ptr())}; - if c_res == 0 { // TODO: convert into CPLErr? - Ok(()) - } - else { - Err(()) + if let Ok(c_key) = CString::new(key.to_owned()){ + if let Ok(c_domain) = CString::new(domain.to_owned()){ + if let Ok(c_value) = CString::new(value.to_owned()){ + let c_res = unsafe { GDALSetMetadataItem(self.get_gdal_object_ptr(), c_key.as_ptr(), c_value.as_ptr(), c_domain.as_ptr())}; + if c_res == 0 { + return Ok(()); + } + } + } } + Err(()) } } diff --git a/src/raster/tests.rs b/src/raster/tests.rs index da3130ea..77f00727 100644 --- a/src/raster/tests.rs +++ b/src/raster/tests.rs @@ -130,6 +130,23 @@ fn test_get_metadata_item() { assert_eq!(meta, Some(String::from("PIXEL"))); } +#[test] +fn test_set_metadata_item() { + + use metadata::Metadata; + + let driver = Driver::get("MEM").unwrap(); + let mut dataset = driver.create("", 1, 1, 1).unwrap(); + + let key = "Test_Key"; + let domain = "Test_Domain"; + let value = "Test_Value"; + let result = dataset.set_metadata_item(key, value, domain); + assert_eq!(result, Ok(())); + + let result = dataset.get_metadata_item(key, domain); + assert_eq!(Some(value.to_owned()), result); +} #[test] fn test_create() { From fdfa509147458ce95e9315dab86f64ad1d3ddef5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20Dr=C3=B6nner?= Date: Thu, 26 May 2016 22:40:44 +0200 Subject: [PATCH 3/3] * added get_description to Metadata trait. * added test for get_description. * added get_description to metadata example. --- examples/metadata.rs | 5 +++++ src/metadata.rs | 10 ++++++++++ src/raster/driver.rs | 10 ++++++++++ src/raster/tests.rs | 12 +++++++----- 4 files changed, 32 insertions(+), 5 deletions(-) diff --git a/examples/metadata.rs b/examples/metadata.rs index 117ceee8..4cd71397 100644 --- a/examples/metadata.rs +++ b/examples/metadata.rs @@ -5,8 +5,13 @@ fn main() { use gdal::raster::dataset::Dataset; use gdal::metadata::Metadata; + let driver = gdal::raster::driver::Driver::get("mem").unwrap(); + println!("driver description: {:?}", driver.get_description()); + let path = Path::new("./fixtures/tinymarble.png"); let dataset = Dataset::open(path).unwrap(); + println!("dataset description: {:?}", dataset.get_description()); + let key = "INTERLEAVE"; let domain = "IMAGE_STRUCTURE"; let meta = dataset.get_metadata_item(key, domain); diff --git a/src/metadata.rs b/src/metadata.rs index 68eb9de8..d63f9bd2 100644 --- a/src/metadata.rs +++ b/src/metadata.rs @@ -5,12 +5,22 @@ use gdal_major_object::MajorObject; #[link(name="gdal")] extern { + fn GDALGetDescription(hGdalMayorObject: *const c_void) -> *const c_char; fn GDALGetMetadataItem(hGdalMayorObject: *const c_void, pszName: *const c_char, pszDomain: *const c_char) -> *const c_char; fn GDALSetMetadataItem(hGdalMayorObject: *const c_void, pszName: *const c_char, pszValue: *const c_char, pszDomain: *const c_char ) -> c_int; } pub trait Metadata: MajorObject { + fn get_description(&self) -> Option{ + let c_res = unsafe { GDALGetDescription(self.get_gdal_object_ptr())}; + if c_res.is_null() { + None + } else { + Some(_string(c_res)) + } + } + fn get_metadata_item(&self, key: &str, domain: &str) -> Option { if let Ok(c_key) = CString::new(key.to_owned()) { if let Ok(c_domain) = CString::new(domain.to_owned()){ diff --git a/src/raster/driver.rs b/src/raster/driver.rs index ce7839da..e659d9f5 100644 --- a/src/raster/driver.rs +++ b/src/raster/driver.rs @@ -4,6 +4,8 @@ use std::sync::{Once, ONCE_INIT}; use utils::_string; use raster::{gdal, Dataset}; use raster::types::GdalType; +use gdal_major_object::MajorObject; +use metadata::Metadata; static START: Once = ONCE_INIT; @@ -93,3 +95,11 @@ impl Driver { }; } } + +impl MajorObject for Driver { + unsafe fn get_gdal_object_ptr(&self) -> *const c_void { + return self.c_driver; + } +} + +impl Metadata for Driver {} diff --git a/src/raster/tests.rs b/src/raster/tests.rs index 77f00727..84fb211b 100644 --- a/src/raster/tests.rs +++ b/src/raster/tests.rs @@ -1,6 +1,7 @@ use std::path::Path; use super::{ByteBuffer, Driver, Dataset}; use super::gdal_enums::{GDALDataType}; +use metadata::Metadata; macro_rules! fixture { @@ -114,10 +115,14 @@ fn test_get_dataset_driver() { } #[test] -fn test_get_metadata_item() { +fn test_get_description() { - use metadata::Metadata; + let driver = Driver::get("mem").unwrap(); + assert_eq!(driver.get_description(), Some("MEM".to_owned())); +} +#[test] +fn test_get_metadata_item() { let dataset = Dataset::open(fixture!("tinymarble.png")).unwrap(); let key = "None"; let domain = "None"; @@ -132,9 +137,6 @@ fn test_get_metadata_item() { #[test] fn test_set_metadata_item() { - - use metadata::Metadata; - let driver = Driver::get("MEM").unwrap(); let mut dataset = driver.create("", 1, 1, 1).unwrap();