diff --git a/examples/metadata.rs b/examples/metadata.rs new file mode 100644 index 00000000..4cd71397 --- /dev/null +++ b/examples/metadata.rs @@ -0,0 +1,20 @@ +extern crate gdal; + +fn main() { + use std::path::Path; + 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); + 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..d63f9bd2 --- /dev/null +++ b/src/metadata.rs @@ -0,0 +1,50 @@ +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 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()){ + 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<(), ()> { + 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/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/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 d17f0b20..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 { @@ -113,6 +114,41 @@ fn test_get_dataset_driver() { assert_eq!(driver.long_name(), "Portable Network Graphics"); } +#[test] +fn test_get_description() { + + 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"; + 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_set_metadata_item() { + 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() { 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 {