mirror of
https://github.com/georust/netcdf.git
synced 2026-01-25 15:02:13 +00:00
fix lifetime bounds and simplify Variable
This commit is contained in:
parent
d0ea914d67
commit
b461886fbc
48
src/file.rs
48
src/file.rs
@ -136,13 +136,13 @@ impl ReadOnlyFile {
|
||||
}
|
||||
|
||||
/// Get a variable from the group
|
||||
pub fn variable<'g>(&'g self, name: &str) -> error::Result<Option<Variable<'g, 'g>>> {
|
||||
pub fn variable<'f>(&'f self, name: &str) -> error::Result<Option<Variable<'f>>> {
|
||||
Variable::find_from_name(self.ncid(), name)
|
||||
}
|
||||
/// Iterate over all variables in a group
|
||||
pub fn variables<'f>(
|
||||
&'f self,
|
||||
) -> error::Result<impl Iterator<Item = error::Result<Variable<'f, 'f>>>> {
|
||||
) -> error::Result<impl Iterator<Item = error::Result<Variable<'f>>>> {
|
||||
super::variable::variables_at_ncid(self.ncid())
|
||||
}
|
||||
|
||||
@ -164,18 +164,18 @@ impl ReadOnlyFile {
|
||||
super::dimension::dimension_from_name(self.ncid(), name)
|
||||
}
|
||||
/// Iterator over all dimensions in the root group
|
||||
pub fn dimensions<'g>(
|
||||
&'g self,
|
||||
) -> error::Result<impl Iterator<Item = error::Result<Dimension<'g>>>> {
|
||||
pub fn dimensions<'f>(
|
||||
&'f self,
|
||||
) -> error::Result<impl Iterator<Item = error::Result<Dimension<'f>>>> {
|
||||
super::dimension::dimensions_from_location(self.ncid())
|
||||
}
|
||||
|
||||
/// Get a group
|
||||
pub fn group(&self, name: &str) -> error::Result<Option<Group>> {
|
||||
pub fn group<'f>(&'f self, name: &str) -> error::Result<Option<Group<'f>>> {
|
||||
super::group::group_from_name(self.ncid(), name)
|
||||
}
|
||||
/// Iterator over all subgroups in the root group
|
||||
pub fn groups<'g>(&'g self) -> error::Result<impl Iterator<Item = Group<'g>>> {
|
||||
pub fn groups<'f>(&'f self) -> error::Result<impl Iterator<Item = Group<'f>>> {
|
||||
super::group::groups_at_ncid(self.ncid())
|
||||
}
|
||||
}
|
||||
@ -198,17 +198,25 @@ impl MutableFile {
|
||||
}
|
||||
|
||||
/// Get a mutable variable from the group
|
||||
pub fn variable_mut<'g>(
|
||||
&'g mut self,
|
||||
name: &str,
|
||||
) -> error::Result<Option<VariableMut<'g, 'g>>> {
|
||||
pub fn variable_mut<'f>(&'f mut self, name: &str) -> error::Result<Option<VariableMut<'f>>> {
|
||||
self.variable(name)
|
||||
.map(|var| var.map(|var| VariableMut(var, PhantomData)))
|
||||
}
|
||||
/// Iterate over all variables in the root group, with mutable access
|
||||
///
|
||||
/// # Examples
|
||||
/// Use this to get multiple writable variables
|
||||
/// ```no_run
|
||||
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// let mut file = netcdf::append("file.nc")?;
|
||||
/// let mut vars = file.variables_mut()?.collect::<Result<Vec<_>, _>>()?;
|
||||
/// vars[0].put_value(1_u8, Some(&[2, 5]))?;
|
||||
/// vars[1].put_value(1_u8, Some(&[5, 2]))?;
|
||||
/// # Ok(()) }
|
||||
/// ```
|
||||
pub fn variables_mut<'f>(
|
||||
&'f mut self,
|
||||
) -> error::Result<impl Iterator<Item = error::Result<VariableMut<'f, 'f>>>> {
|
||||
) -> error::Result<impl Iterator<Item = error::Result<VariableMut<'f>>>> {
|
||||
self.variables()
|
||||
.map(|v| v.map(|var| var.map(|var| VariableMut(var, PhantomData))))
|
||||
}
|
||||
@ -233,7 +241,7 @@ impl MutableFile {
|
||||
}
|
||||
|
||||
/// Adds a dimension with the given name and size. A size of zero gives an unlimited dimension
|
||||
pub fn add_dimension<'g>(&'g mut self, name: &str, len: usize) -> error::Result<Dimension<'g>> {
|
||||
pub fn add_dimension<'f>(&'f mut self, name: &str, len: usize) -> error::Result<Dimension<'f>> {
|
||||
let _l = LOCK.lock().unwrap();
|
||||
super::dimension::add_dimension_at(self.ncid(), name, len)
|
||||
}
|
||||
@ -256,7 +264,7 @@ impl MutableFile {
|
||||
&'f mut self,
|
||||
name: &str,
|
||||
dims: &[&str],
|
||||
) -> error::Result<VariableMut<'f, 'f>>
|
||||
) -> error::Result<VariableMut<'f>>
|
||||
where
|
||||
T: Numeric,
|
||||
{
|
||||
@ -264,17 +272,21 @@ impl MutableFile {
|
||||
VariableMut::add_from_str(self.ncid(), T::NCTYPE, name, dims)
|
||||
}
|
||||
/// Adds a variable with a basic type of string
|
||||
pub fn add_string_variable(&mut self, name: &str, dims: &[&str]) -> error::Result<VariableMut> {
|
||||
pub fn add_string_variable<'f>(
|
||||
&'f mut self,
|
||||
name: &str,
|
||||
dims: &[&str],
|
||||
) -> error::Result<VariableMut<'f>> {
|
||||
let _l = LOCK.lock().unwrap();
|
||||
VariableMut::add_from_str(self.ncid(), NC_STRING, name, dims)
|
||||
}
|
||||
/// Adds a variable from a set of unique identifiers, recursing upwards
|
||||
/// from the current group if necessary.
|
||||
pub fn add_variable_from_identifiers<T>(
|
||||
&mut self,
|
||||
pub fn add_variable_from_identifiers<'f, T>(
|
||||
&'f mut self,
|
||||
name: &str,
|
||||
dims: &[dimension::Identifier],
|
||||
) -> error::Result<VariableMut>
|
||||
) -> error::Result<VariableMut<'f>>
|
||||
where
|
||||
T: Numeric,
|
||||
{
|
||||
|
||||
79
src/group.rs
79
src/group.rs
@ -54,13 +54,19 @@ impl<'f> Group<'f> {
|
||||
}
|
||||
|
||||
/// Get a variable from the group
|
||||
pub fn variable<'g>(&'g self, name: &str) -> error::Result<Option<Variable<'f, 'g>>> {
|
||||
pub fn variable<'g>(&'g self, name: &str) -> error::Result<Option<Variable<'g>>>
|
||||
where
|
||||
'f: 'g,
|
||||
{
|
||||
Variable::find_from_name(self.id(), name)
|
||||
}
|
||||
/// Iterate over all variables in a group
|
||||
pub fn variables<'g>(
|
||||
&'g self,
|
||||
) -> error::Result<impl Iterator<Item = error::Result<Variable<'f, 'g>>>> {
|
||||
) -> error::Result<impl Iterator<Item = error::Result<Variable<'g>>>>
|
||||
where
|
||||
'f: 'g,
|
||||
{
|
||||
super::variable::variables_at_ncid(self.id())
|
||||
}
|
||||
|
||||
@ -70,57 +76,80 @@ impl<'f> Group<'f> {
|
||||
Attribute::find_from_name(self.ncid, None, name)
|
||||
}
|
||||
/// Get all attributes in the group
|
||||
pub fn attributes(&self) -> error::Result<impl Iterator<Item = error::Result<Attribute>>> {
|
||||
pub fn attributes<'a>(
|
||||
&'a self,
|
||||
) -> error::Result<impl Iterator<Item = error::Result<Attribute<'a>>>> {
|
||||
// Need to lock when reading the first attribute (per group)
|
||||
let _l = super::LOCK.lock().unwrap();
|
||||
crate::attribute::AttributeIterator::new(self.ncid, None)
|
||||
}
|
||||
|
||||
/// Get a single dimension
|
||||
pub fn dimension(&self, name: &str) -> error::Result<Option<Dimension>> {
|
||||
pub fn dimension<'g>(&'g self, name: &str) -> error::Result<Option<Dimension<'g>>>
|
||||
where
|
||||
'f: 'g,
|
||||
{
|
||||
super::dimension::dimension_from_name(self.id(), name)
|
||||
}
|
||||
/// Iterator over all dimensions
|
||||
pub fn dimensions<'g>(
|
||||
&'g self,
|
||||
) -> error::Result<impl Iterator<Item = error::Result<Dimension<'g>>>> {
|
||||
) -> error::Result<impl Iterator<Item = error::Result<Dimension<'g>>>>
|
||||
where
|
||||
'f: 'g,
|
||||
{
|
||||
super::dimension::dimensions_from_location(self.id())
|
||||
}
|
||||
|
||||
/// Get a group
|
||||
pub fn group(&self, name: &str) -> error::Result<Option<Self>> {
|
||||
pub fn group<'g>(&'g self, name: &str) -> error::Result<Option<Group<'g>>>
|
||||
where
|
||||
'f: 'g,
|
||||
{
|
||||
group_from_name(self.id(), name)
|
||||
}
|
||||
/// Iterator over all subgroups in this group
|
||||
pub fn groups<'g>(&'g self) -> error::Result<impl Iterator<Item = Group<'g>>> {
|
||||
pub fn groups<'g>(&'g self) -> error::Result<impl Iterator<Item = Group<'g>>>
|
||||
where
|
||||
'f: 'g,
|
||||
{
|
||||
groups_at_ncid(self.id())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'f> GroupMut<'f> {
|
||||
/// Get a mutable variable from the group
|
||||
pub fn variable_mut<'g>(
|
||||
&'g mut self,
|
||||
name: &str,
|
||||
) -> error::Result<Option<VariableMut<'f, 'g>>> {
|
||||
pub fn variable_mut<'g>(&'g mut self, name: &str) -> error::Result<Option<VariableMut<'g>>>
|
||||
where
|
||||
'f: 'g,
|
||||
{
|
||||
self.variable(name)
|
||||
.map(|v| v.map(|v| VariableMut(v, PhantomData)))
|
||||
}
|
||||
/// Iterate over all variables in a group, with mutable access
|
||||
pub fn variables_mut<'g>(
|
||||
&'g mut self,
|
||||
) -> error::Result<impl Iterator<Item = error::Result<VariableMut<'f, 'g>>>> {
|
||||
) -> error::Result<impl Iterator<Item = error::Result<VariableMut<'g>>>>
|
||||
where
|
||||
'f: 'g,
|
||||
{
|
||||
self.variables()
|
||||
.map(|var| var.map(|var| var.map(|var| VariableMut(var, PhantomData))))
|
||||
}
|
||||
|
||||
/// Mutable access to subgroup
|
||||
pub fn group_mut(&'f mut self, name: &str) -> error::Result<Option<Self>> {
|
||||
pub fn group_mut<'g>(&'g mut self, name: &str) -> error::Result<Option<GroupMut<'g>>>
|
||||
where
|
||||
'f: 'g,
|
||||
{
|
||||
self.group(name)
|
||||
.map(|g| g.map(|g| GroupMut(g, PhantomData)))
|
||||
}
|
||||
/// Iterator over all groups (mutable access)
|
||||
pub fn groups_mut(&'f mut self) -> error::Result<impl Iterator<Item = GroupMut<'f>>> {
|
||||
pub fn groups_mut<'g>(&'g mut self) -> error::Result<impl Iterator<Item = GroupMut<'g>>>
|
||||
where
|
||||
'f: 'g,
|
||||
{
|
||||
self.groups().map(|g| g.map(|g| GroupMut(g, PhantomData)))
|
||||
}
|
||||
|
||||
@ -140,7 +169,7 @@ impl<'f> GroupMut<'f> {
|
||||
}
|
||||
|
||||
/// Adds a dimension with unbounded size
|
||||
pub fn add_unlimited_dimension(&mut self, name: &str) -> error::Result<Dimension> {
|
||||
pub fn add_unlimited_dimension<'g>(&'g mut self, name: &str) -> error::Result<Dimension<'g>> {
|
||||
self.add_dimension(name, 0)
|
||||
}
|
||||
|
||||
@ -161,7 +190,10 @@ impl<'f> GroupMut<'f> {
|
||||
}
|
||||
|
||||
/// Add an empty group to the dataset
|
||||
pub fn add_group(&mut self, name: &str) -> error::Result<Self> {
|
||||
pub fn add_group<'g>(&'g mut self, name: &str) -> error::Result<GroupMut<'g>>
|
||||
where
|
||||
'f: 'g,
|
||||
{
|
||||
let _l = LOCK.lock().unwrap();
|
||||
Self::add_group_at(self.id(), name)
|
||||
}
|
||||
@ -174,25 +206,30 @@ impl<'f> GroupMut<'f> {
|
||||
&'g mut self,
|
||||
name: &str,
|
||||
dims: &[&str],
|
||||
) -> error::Result<VariableMut<'f, 'g>>
|
||||
) -> error::Result<VariableMut<'g>>
|
||||
where
|
||||
T: Numeric,
|
||||
'f: 'g,
|
||||
{
|
||||
let _l = LOCK.lock().unwrap();
|
||||
VariableMut::add_from_str(self.id(), T::NCTYPE, name, dims)
|
||||
}
|
||||
/// Adds a variable with a basic type of string
|
||||
pub fn add_string_variable(&mut self, name: &str, dims: &[&str]) -> error::Result<VariableMut> {
|
||||
pub fn add_string_variable<'g>(
|
||||
&mut self,
|
||||
name: &str,
|
||||
dims: &[&str],
|
||||
) -> error::Result<VariableMut<'g>> {
|
||||
let _l = LOCK.lock().unwrap();
|
||||
VariableMut::add_from_str(self.id(), NC_STRING, name, dims)
|
||||
}
|
||||
/// Adds a variable from a set of unique identifiers, recursing upwards
|
||||
/// from the current group if necessary.
|
||||
pub fn add_variable_from_identifiers<T>(
|
||||
&mut self,
|
||||
pub fn add_variable_from_identifiers<'g, T>(
|
||||
&'g mut self,
|
||||
name: &str,
|
||||
dims: &[super::dimension::Identifier],
|
||||
) -> error::Result<VariableMut>
|
||||
) -> error::Result<VariableMut<'g>>
|
||||
where
|
||||
T: Numeric,
|
||||
{
|
||||
|
||||
@ -16,9 +16,9 @@ use std::marker::Sized;
|
||||
#[allow(clippy::doc_markdown)]
|
||||
/// This struct defines a netCDF variable.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Variable<'f, 'g> {
|
||||
pub struct Variable<'g> {
|
||||
/// The variable name
|
||||
pub(crate) dimensions: Vec<Dimension<'f>>,
|
||||
pub(crate) dimensions: Vec<Dimension<'g>>,
|
||||
/// the netcdf variable type identifier (from netcdf-sys)
|
||||
pub(crate) vartype: nc_type,
|
||||
pub(crate) ncid: nc_type,
|
||||
@ -27,14 +27,14 @@ pub struct Variable<'f, 'g> {
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
/// Mutable access to a variable
|
||||
pub struct VariableMut<'f, 'g>(
|
||||
pub(crate) Variable<'f, 'g>,
|
||||
/// Mutable access to a variable.
|
||||
pub struct VariableMut<'g>(
|
||||
pub(crate) Variable<'g>,
|
||||
pub(crate) PhantomData<&'g mut nc_type>,
|
||||
);
|
||||
|
||||
impl<'f, 'g> std::ops::Deref for VariableMut<'f, 'g> {
|
||||
type Target = Variable<'f, 'g>;
|
||||
impl<'g> std::ops::Deref for VariableMut<'g> {
|
||||
type Target = Variable<'g>;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
@ -52,11 +52,8 @@ pub enum Endianness {
|
||||
}
|
||||
|
||||
#[allow(clippy::len_without_is_empty)]
|
||||
impl<'f, 'g> Variable<'f, 'g> {
|
||||
pub(crate) fn find_from_name(
|
||||
ncid: nc_type,
|
||||
name: &str,
|
||||
) -> error::Result<Option<Variable<'f, 'g>>> {
|
||||
impl<'g> Variable<'g> {
|
||||
pub(crate) fn find_from_name(ncid: nc_type, name: &str) -> error::Result<Option<Variable<'g>>> {
|
||||
let cname = super::utils::short_name_to_bytes(name)?;
|
||||
let mut varid = 0;
|
||||
let e = unsafe { nc_inq_varid(ncid, cname.as_ptr() as *const _, &mut varid) };
|
||||
@ -151,7 +148,7 @@ impl<'f, 'g> Variable<'f, 'g> {
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<'f, 'g> VariableMut<'f, 'g> {
|
||||
impl<'g> VariableMut<'g> {
|
||||
/// Sets compression on the variable. Must be set before filling in data.
|
||||
///
|
||||
/// `deflate_level` can take a value 0..=9, with 0 being no
|
||||
@ -200,7 +197,7 @@ impl<'f, 'g> VariableMut<'f, 'g> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'f, 'g> Variable<'f, 'g> {
|
||||
impl<'g> Variable<'g> {
|
||||
/// Checks for array mismatch
|
||||
fn check_indices(&self, indices: &[usize], putting: bool) -> error::Result<()> {
|
||||
if indices.len() != self.dimensions.len() {
|
||||
@ -684,7 +681,7 @@ impl std::ops::Deref for NcString {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'f, 'g> VariableMut<'f, 'g> {
|
||||
impl<'g> VariableMut<'g> {
|
||||
/// Adds an attribute to the variable
|
||||
pub fn add_attribute<T>(&mut self, name: &str, val: T) -> error::Result<Attribute>
|
||||
where
|
||||
@ -695,7 +692,7 @@ impl<'f, 'g> VariableMut<'f, 'g> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'f, 'g> Variable<'f, 'g> {
|
||||
impl<'g> Variable<'g> {
|
||||
/// Fetches one specific value at specific indices
|
||||
/// indices must has the same length as self.dimensions.
|
||||
pub fn value<T: Numeric>(&self, indices: Option<&[usize]>) -> error::Result<T> {
|
||||
@ -900,7 +897,7 @@ impl<'f, 'g> Variable<'f, 'g> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'f, 'g> VariableMut<'f, 'g> {
|
||||
impl<'g> VariableMut<'g> {
|
||||
/// Put a single value at `indices`
|
||||
pub fn put_value<T: Numeric>(
|
||||
&mut self,
|
||||
@ -1098,7 +1095,7 @@ impl<'f, 'g> VariableMut<'f, 'g> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'f, 'g> VariableMut<'f, 'g> {
|
||||
impl<'g> VariableMut<'g> {
|
||||
pub(crate) fn add_from_str(
|
||||
ncid: nc_type,
|
||||
xtype: nc_type,
|
||||
@ -1141,12 +1138,9 @@ impl<'f, 'g> VariableMut<'f, 'g> {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn variables_at_ncid<'f, 'g>(
|
||||
pub(crate) fn variables_at_ncid<'g>(
|
||||
ncid: nc_type,
|
||||
) -> error::Result<impl Iterator<Item = error::Result<Variable<'f, 'g>>>>
|
||||
where
|
||||
'f: 'g,
|
||||
{
|
||||
) -> error::Result<impl Iterator<Item = error::Result<Variable<'g>>>> {
|
||||
let mut nvars = 0;
|
||||
unsafe {
|
||||
error::checked(nc_inq_varids(ncid, &mut nvars, std::ptr::null_mut()))?;
|
||||
@ -1176,12 +1170,12 @@ where
|
||||
}))
|
||||
}
|
||||
|
||||
pub(crate) fn add_variable_from_identifiers<'f, 'g>(
|
||||
pub(crate) fn add_variable_from_identifiers<'g>(
|
||||
ncid: nc_type,
|
||||
name: &str,
|
||||
dims: &[super::dimension::Identifier],
|
||||
xtype: nc_type,
|
||||
) -> error::Result<VariableMut<'f, 'g>> {
|
||||
) -> error::Result<VariableMut<'g>> {
|
||||
let cname = super::utils::short_name_to_bytes(name)?;
|
||||
|
||||
let dimensions = dims
|
||||
|
||||
14
tests/lib.rs
14
tests/lib.rs
@ -1292,14 +1292,12 @@ fn dimension_identifiers() {
|
||||
let g = &mut file.add_group("g").unwrap();
|
||||
let dim = &g.add_dimension("x", 5).unwrap();
|
||||
let vgid = dim.identifier();
|
||||
let mut gg = file
|
||||
.group_mut("g")
|
||||
.unwrap()
|
||||
.unwrap()
|
||||
.add_group("g")
|
||||
.unwrap();
|
||||
let dim = &gg.add_dimension("x", 7).unwrap();
|
||||
let vggid = dim.identifier();
|
||||
let vggid = {
|
||||
let mut g = file.group_mut("g").unwrap().unwrap();
|
||||
let mut gg = g.add_group("g").unwrap();
|
||||
let dim = &gg.add_dimension("x", 7).unwrap();
|
||||
dim.identifier()
|
||||
};
|
||||
|
||||
// Create variables
|
||||
file.add_variable_from_identifiers::<i8>("v_self_id", &[vrootid])
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user