fix lifetime bounds and simplify Variable

This commit is contained in:
Magnus Ulimoen 2020-01-06 19:02:25 +01:00
parent d0ea914d67
commit b461886fbc
4 changed files with 113 additions and 72 deletions

View File

@ -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,
{

View File

@ -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,
{

View File

@ -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

View File

@ -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])