-
Notifications
You must be signed in to change notification settings - Fork 95
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
allow reading dimensions from md groups #291
Changes from 6 commits
c89d8b4
07dbe43
62a42fc
3392aca
fbe0e09
9af36a6
952eb06
c482412
ccfa51d
e053d7c
b830df0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,12 +10,12 @@ use gdal_sys::{ | |
GDALAttributeRelease, GDALDataType, GDALDimensionGetIndexingVariable, GDALDimensionGetName, | ||
GDALDimensionGetSize, GDALDimensionHS, GDALDimensionRelease, GDALExtendedDataTypeClass, | ||
GDALExtendedDataTypeGetClass, GDALExtendedDataTypeGetNumericDataType, GDALExtendedDataTypeH, | ||
GDALExtendedDataTypeRelease, GDALGroupGetAttribute, GDALGroupGetGroupNames, | ||
GDALGroupGetMDArrayNames, GDALGroupGetName, GDALGroupH, GDALGroupOpenGroup, | ||
GDALGroupOpenMDArray, GDALGroupRelease, GDALMDArrayGetAttribute, GDALMDArrayGetDataType, | ||
GDALMDArrayGetDimensionCount, GDALMDArrayGetDimensions, GDALMDArrayGetNoDataValueAsDouble, | ||
GDALMDArrayGetSpatialRef, GDALMDArrayGetTotalElementsCount, GDALMDArrayGetUnit, GDALMDArrayH, | ||
GDALMDArrayRelease, OSRDestroySpatialReference, VSIFree, | ||
GDALExtendedDataTypeRelease, GDALGroupGetAttribute, GDALGroupGetDimensions, | ||
GDALGroupGetGroupNames, GDALGroupGetMDArrayNames, GDALGroupGetName, GDALGroupH, | ||
GDALGroupOpenGroup, GDALGroupOpenMDArray, GDALGroupRelease, GDALMDArrayGetAttribute, | ||
GDALMDArrayGetDataType, GDALMDArrayGetDimensionCount, GDALMDArrayGetDimensions, | ||
GDALMDArrayGetNoDataValueAsDouble, GDALMDArrayGetSpatialRef, GDALMDArrayGetTotalElementsCount, | ||
GDALMDArrayGetUnit, GDALMDArrayH, GDALMDArrayRelease, OSRDestroySpatialReference, VSIFree, | ||
}; | ||
use libc::c_void; | ||
use std::ffi::CString; | ||
|
@@ -37,11 +37,17 @@ pub struct MDArray<'a> { | |
} | ||
|
||
#[derive(Debug)] | ||
enum GroupOrDimension<'a> { | ||
pub enum GroupOrDimension<'a> { | ||
Group { _group: &'a Group<'a> }, | ||
Dimension { _dimension: &'a Dimension<'a> }, | ||
} | ||
|
||
#[derive(Debug)] | ||
pub enum GroupOrArray<'a> { | ||
Group { _group: &'a Group<'a> }, | ||
MDArray { _md_array: &'a MDArray<'a> }, | ||
} | ||
|
||
impl Drop for MDArray<'_> { | ||
fn drop(&mut self) { | ||
unsafe { | ||
|
@@ -90,16 +96,21 @@ impl<'a> MDArray<'a> { | |
let c_dimensions = | ||
GDALMDArrayGetDimensions(self.c_mdarray, std::ptr::addr_of_mut!(num_dimensions)); | ||
|
||
if c_dimensions.is_null() { | ||
return Err(_last_null_pointer_err("GDALMDArrayGetDimensions")); | ||
// `num_dimensions` is `0`, we can safely return an empty vector | ||
// `GDALMDArrayGetDimensions` does not state that errors can occur | ||
if num_dimensions > 0 && c_dimensions.is_null() { | ||
return Err(_last_null_pointer_err("GDALGroupGetDimensions")); | ||
} | ||
|
||
let dimensions_ref = std::slice::from_raw_parts_mut(c_dimensions, num_dimensions); | ||
|
||
let mut dimensions: Vec<Dimension> = Vec::with_capacity(num_dimensions); | ||
|
||
for c_dimension in dimensions_ref { | ||
let dimension = Dimension::from_c_dimension(self, *c_dimension); | ||
let dimension = Dimension::from_c_dimension( | ||
GroupOrArray::MDArray { _md_array: self }, | ||
*c_dimension, | ||
); | ||
dimensions.push(dimension); | ||
} | ||
|
||
|
@@ -413,7 +424,7 @@ impl<'a> Group<'a> { | |
} | ||
} | ||
|
||
pub fn open_group(&self, name: &str, options: CslStringList) -> Result<Group> { | ||
pub fn open_group(&'_ self, name: &str, options: CslStringList) -> Result<Group<'a>> { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm a bit groggy right now, does There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, I prevented Group from having the lifetime of self. It needs the lifetime of the dataset. |
||
let name = CString::new(name)?; | ||
|
||
unsafe { | ||
|
@@ -440,13 +451,45 @@ impl<'a> Group<'a> { | |
Ok(Attribute::from_c_attribute(c_attribute)) | ||
} | ||
} | ||
|
||
pub fn dimensions(&self, options: CslStringList) -> Result<Vec<Dimension>> { | ||
unsafe { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please try to make this There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
let mut num_dimensions: usize = 0; | ||
let c_dimensions = GDALGroupGetDimensions( | ||
self.c_group, | ||
std::ptr::addr_of_mut!(num_dimensions), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not necessarily against it, but I'd expect to see There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
options.as_ptr(), | ||
); | ||
|
||
// `num_dimensions` is `0`, we can safely return an empty vector | ||
// `GDALGroupGetDimensions` does not state that errors can occur | ||
if num_dimensions > 0 && c_dimensions.is_null() { | ||
return Err(_last_null_pointer_err("GDALGroupGetDimensions")); | ||
} | ||
|
||
let dimensions_ref = std::slice::from_raw_parts_mut(c_dimensions, num_dimensions); | ||
|
||
let mut dimensions: Vec<Dimension> = Vec::with_capacity(num_dimensions); | ||
|
||
for c_dimension in dimensions_ref { | ||
let dimension = | ||
Dimension::from_c_dimension(GroupOrArray::Group { _group: self }, *c_dimension); | ||
dimensions.push(dimension); | ||
} | ||
|
||
// only free the array, not the dimensions themselves | ||
VSIFree(c_dimensions as *mut c_void); | ||
|
||
Ok(dimensions) | ||
} | ||
} | ||
} | ||
|
||
/// A `GDALDimension` with name and size | ||
#[derive(Debug)] | ||
pub struct Dimension<'a> { | ||
c_dimension: *mut GDALDimensionHS, | ||
_md_array: &'a MDArray<'a>, | ||
_parent: GroupOrArray<'a>, | ||
} | ||
|
||
impl Drop for Dimension<'_> { | ||
|
@@ -462,10 +505,13 @@ impl<'a> Dimension<'a> { | |
/// | ||
/// # Safety | ||
/// This method operates on a raw C pointer | ||
pub fn from_c_dimension(_md_array: &'a MDArray<'a>, c_dimension: *mut GDALDimensionHS) -> Self { | ||
pub unsafe fn from_c_dimension( | ||
_parent: GroupOrArray<'a>, | ||
c_dimension: *mut GDALDimensionHS, | ||
) -> Self { | ||
Self { | ||
c_dimension, | ||
_md_array, | ||
_parent, | ||
} | ||
} | ||
pub fn size(&self) -> usize { | ||
|
@@ -708,6 +754,17 @@ mod tests { | |
}; | ||
let dataset = Dataset::open_ex("fixtures/byte_no_cf.nc", dataset_options).unwrap(); | ||
let root_group = dataset.root_group().unwrap(); | ||
|
||
// group dimensions | ||
let group_dimensions = root_group.dimensions(CslStringList::new()).unwrap(); | ||
let group_dimensions_names: Vec<String> = group_dimensions | ||
.into_iter() | ||
.map(|dimensions| dimensions.name()) | ||
.collect(); | ||
assert_eq!(group_dimensions_names, vec!["x", "y"]); | ||
|
||
// array dimensions | ||
|
||
let array_name = "Band1".to_string(); | ||
let options = CslStringList::new(); //Driver specific options determining how the array should be opened. Pass nullptr for default behavior. | ||
let md_array = root_group.open_md_array(&array_name, options).unwrap(); | ||
|
@@ -718,6 +775,7 @@ mod tests { | |
} | ||
assert_eq!(dimension_names, vec!["y".to_string(), "x".to_string()]) | ||
} | ||
|
||
#[test] | ||
fn test_dimension_size() { | ||
let dataset_options = DatasetOptions { | ||
|
@@ -796,6 +854,7 @@ mod tests { | |
let dataset = Dataset::open_ex("fixtures/byte_no_cf.nc", dataset_options).unwrap(); | ||
|
||
let root_group = dataset.root_group().unwrap(); | ||
|
||
let md_array = root_group | ||
.open_md_array("Band1", CslStringList::new()) | ||
.unwrap(); | ||
|
@@ -866,6 +925,12 @@ mod tests { | |
let group_science = root_group | ||
.open_group("science", CslStringList::new()) | ||
.unwrap(); | ||
|
||
assert!(group_science | ||
.dimensions(Default::default()) | ||
.unwrap() | ||
.is_empty()); | ||
|
||
let group_grids = group_science | ||
.open_group("grids", CslStringList::new()) | ||
.unwrap(); | ||
|
@@ -914,6 +979,9 @@ mod tests { | |
let group_grids = group_science | ||
.open_group("grids", CslStringList::new()) | ||
.unwrap(); | ||
|
||
drop(group_science); // check that `Group`s do not borrow each other | ||
|
||
let group_data = group_grids | ||
.open_group("data", CslStringList::new()) | ||
.unwrap(); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
952eb06