diff --git a/netcdf-src/Cargo.toml b/netcdf-src/Cargo.toml index 676eec2..da29214 100644 --- a/netcdf-src/Cargo.toml +++ b/netcdf-src/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "netcdf-src" -version = "0.3.0" +version = "0.3.1" authors = ["Magnus Ulimoen "] edition = "2021" description = "Build scripts for building `netCDF` from source" diff --git a/netcdf-src/README.md b/netcdf-src/README.md index be79ac9..f9e855b 100644 --- a/netcdf-src/README.md +++ b/netcdf-src/README.md @@ -2,4 +2,4 @@ Dummy crate for building `netCDF` from source -The current pinned version is 4.7.4 +The current pinned version is 4.9.2 diff --git a/netcdf-src/src/lib.rs b/netcdf-src/src/lib.rs index 96b6cfc..d811de9 100644 --- a/netcdf-src/src/lib.rs +++ b/netcdf-src/src/lib.rs @@ -1,3 +1,3 @@ //! Dummy crate for building `netCDF` from source //! -//! The current pinned version is 4.7.4 +//! The current pinned version is 4.9.2 diff --git a/netcdf/Cargo.toml b/netcdf/Cargo.toml index b0919eb..71645cd 100644 --- a/netcdf/Cargo.toml +++ b/netcdf/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "netcdf" -version = "0.8.2" +version = "0.8.3" authors = [ "Michael Hiley ", "Magnus Ulimoen " diff --git a/netcdf/src/attribute.rs b/netcdf/src/attribute.rs index 93f8392..3bf7b25 100644 --- a/netcdf/src/attribute.rs +++ b/netcdf/src/attribute.rs @@ -3,7 +3,6 @@ #![allow(clippy::similar_names)] use super::error; use netcdf_sys::*; -use std::convert::TryInto; use std::ffi::{CStr, CString}; use std::marker::PhantomData; use std::os::raw::c_char; @@ -887,3 +886,182 @@ fn conversion() { let x = 1.0f32; let _b: AttrValue = x.into(); } + +impl TryFrom for u8 { + type Error = error::Error; + fn try_from(attr: AttrValue) -> Result { + match attr { + AttrValue::Uchar(x) => Ok(x), + AttrValue::Schar(x) => (x).try_into().map_err(error::Error::Conversion), + AttrValue::Ushort(x) => (x).try_into().map_err(error::Error::Conversion), + AttrValue::Short(x) => (x).try_into().map_err(error::Error::Conversion), + AttrValue::Uint(x) => (x).try_into().map_err(error::Error::Conversion), + AttrValue::Int(x) => (x).try_into().map_err(error::Error::Conversion), + AttrValue::Ulonglong(x) => (x).try_into().map_err(error::Error::Conversion), + AttrValue::Longlong(x) => (x).try_into().map_err(error::Error::Conversion), + _ => Err("Conversion not supported".into()), + } + } +} + +impl TryFrom for i8 { + type Error = error::Error; + fn try_from(attr: AttrValue) -> Result { + match attr { + AttrValue::Uchar(x) => (x).try_into().map_err(error::Error::Conversion), + AttrValue::Schar(x) => Ok(x), + AttrValue::Ushort(x) => (x).try_into().map_err(error::Error::Conversion), + AttrValue::Short(x) => (x).try_into().map_err(error::Error::Conversion), + AttrValue::Uint(x) => (x).try_into().map_err(error::Error::Conversion), + AttrValue::Int(x) => (x).try_into().map_err(error::Error::Conversion), + AttrValue::Ulonglong(x) => (x).try_into().map_err(error::Error::Conversion), + AttrValue::Longlong(x) => (x).try_into().map_err(error::Error::Conversion), + _ => Err("Conversion not supported".into()), + } + } +} + +impl TryFrom for u16 { + type Error = error::Error; + fn try_from(attr: AttrValue) -> Result { + match attr { + AttrValue::Uchar(x) => Ok((x).into()), + AttrValue::Schar(x) => (x).try_into().map_err(error::Error::Conversion), + AttrValue::Ushort(x) => Ok(x), + AttrValue::Short(x) => (x).try_into().map_err(error::Error::Conversion), + AttrValue::Uint(x) => (x).try_into().map_err(error::Error::Conversion), + AttrValue::Int(x) => (x).try_into().map_err(error::Error::Conversion), + AttrValue::Ulonglong(x) => (x).try_into().map_err(error::Error::Conversion), + AttrValue::Longlong(x) => (x).try_into().map_err(error::Error::Conversion), + _ => Err("Conversion not supported".into()), + } + } +} + +impl TryFrom for i16 { + type Error = error::Error; + fn try_from(attr: AttrValue) -> Result { + match attr { + AttrValue::Uchar(x) => Ok((x).into()), + AttrValue::Schar(x) => Ok((x).into()), + AttrValue::Ushort(x) => (x).try_into().map_err(error::Error::Conversion), + AttrValue::Short(x) => Ok(x), + AttrValue::Uint(x) => (x).try_into().map_err(error::Error::Conversion), + AttrValue::Int(x) => (x).try_into().map_err(error::Error::Conversion), + AttrValue::Ulonglong(x) => (x).try_into().map_err(error::Error::Conversion), + AttrValue::Longlong(x) => (x).try_into().map_err(error::Error::Conversion), + _ => Err("Conversion not supported".into()), + } + } +} +impl TryFrom for u32 { + type Error = error::Error; + fn try_from(attr: AttrValue) -> Result { + match attr { + AttrValue::Uchar(x) => Ok((x).into()), + AttrValue::Schar(x) => (x).try_into().map_err(error::Error::Conversion), + AttrValue::Ushort(x) => Ok((x).into()), + AttrValue::Short(x) => (x).try_into().map_err(error::Error::Conversion), + AttrValue::Uint(x) => Ok(x), + AttrValue::Int(x) => (x).try_into().map_err(error::Error::Conversion), + AttrValue::Ulonglong(x) => (x).try_into().map_err(error::Error::Conversion), + AttrValue::Longlong(x) => (x).try_into().map_err(error::Error::Conversion), + _ => Err("Conversion not supported".into()), + } + } +} +impl TryFrom for i32 { + type Error = error::Error; + fn try_from(attr: AttrValue) -> Result { + match attr { + AttrValue::Uchar(x) => Ok((x).into()), + AttrValue::Schar(x) => Ok((x).into()), + AttrValue::Ushort(x) => Ok((x).into()), + AttrValue::Short(x) => Ok((x).into()), + AttrValue::Uint(x) => (x).try_into().map_err(error::Error::Conversion), + AttrValue::Int(x) => Ok(x), + AttrValue::Ulonglong(x) => (x).try_into().map_err(error::Error::Conversion), + AttrValue::Longlong(x) => (x).try_into().map_err(error::Error::Conversion), + _ => Err("Conversion not supported".into()), + } + } +} +impl TryFrom for u64 { + type Error = error::Error; + fn try_from(attr: AttrValue) -> Result { + match attr { + AttrValue::Uchar(x) => Ok((x).into()), + AttrValue::Schar(x) => (x).try_into().map_err(error::Error::Conversion), + AttrValue::Ushort(x) => Ok((x).into()), + AttrValue::Short(x) => (x).try_into().map_err(error::Error::Conversion), + AttrValue::Uint(x) => Ok((x).into()), + AttrValue::Int(x) => (x).try_into().map_err(error::Error::Conversion), + AttrValue::Ulonglong(x) => Ok(x), + AttrValue::Longlong(x) => (x).try_into().map_err(error::Error::Conversion), + _ => Err("Conversion not supported".into()), + } + } +} +impl TryFrom for i64 { + type Error = error::Error; + fn try_from(attr: AttrValue) -> Result { + match attr { + AttrValue::Uchar(x) => Ok((x).into()), + AttrValue::Schar(x) => Ok((x).into()), + AttrValue::Ushort(x) => Ok((x).into()), + AttrValue::Short(x) => Ok((x).into()), + AttrValue::Uint(x) => Ok((x).into()), + AttrValue::Int(x) => Ok((x).into()), + AttrValue::Ulonglong(x) => (x).try_into().map_err(error::Error::Conversion), + AttrValue::Longlong(x) => Ok(x), + _ => Err("Conversion not supported".into()), + } + } +} +impl TryFrom for f32 { + type Error = error::Error; + fn try_from(attr: AttrValue) -> Result { + match attr { + AttrValue::Uchar(x) => Ok(x as _), + AttrValue::Schar(x) => Ok(x as _), + AttrValue::Ushort(x) => Ok(x as _), + AttrValue::Short(x) => Ok(x as _), + AttrValue::Uint(x) => Ok(x as _), + AttrValue::Int(x) => Ok(x as _), + AttrValue::Ulonglong(x) => Ok(x as _), + AttrValue::Longlong(x) => Ok(x as _), + AttrValue::Float(x) => Ok(x), + AttrValue::Double(x) => Ok(x as _), + _ => Err("Conversion not supported".into()), + } + } +} +impl TryFrom for f64 { + type Error = error::Error; + fn try_from(attr: AttrValue) -> Result { + match attr { + AttrValue::Uchar(x) => Ok(x as _), + AttrValue::Schar(x) => Ok(x as _), + AttrValue::Ushort(x) => Ok(x as _), + AttrValue::Short(x) => Ok(x as _), + AttrValue::Uint(x) => Ok(x as _), + AttrValue::Int(x) => Ok(x as _), + AttrValue::Ulonglong(x) => Ok(x as _), + AttrValue::Longlong(x) => Ok(x as _), + AttrValue::Float(x) => Ok(x as _), + AttrValue::Double(x) => Ok(x), + _ => Err("Conversion not supported".into()), + } + } +} + +#[test] +fn roundtrip_attrvalue() { + let x: u8 = 5; + let attr: AttrValue = x.into(); + assert_eq!(x, attr.try_into().unwrap()); + + let x: f32 = 5.0; + let attr: AttrValue = x.into(); + assert_eq!(x, attr.try_into().unwrap()); +} diff --git a/netcdf/src/group.rs b/netcdf/src/group.rs index d417415..16108e4 100644 --- a/netcdf/src/group.rs +++ b/netcdf/src/group.rs @@ -84,6 +84,10 @@ impl<'f> Group<'f> { .unwrap() .map(Result::unwrap) } + /// Get the attribute value + pub fn attribute_value(&self, name: &str) -> Option> { + self.attribute(name).as_ref().map(Attribute::value) + } /// Get a single dimension pub fn dimension<'g>(&'g self, name: &str) -> Option> diff --git a/netcdf/src/variable.rs b/netcdf/src/variable.rs index 0b4be2a..2ffaf88 100644 --- a/netcdf/src/variable.rs +++ b/netcdf/src/variable.rs @@ -128,6 +128,10 @@ impl<'g> Variable<'g> { .expect("Could not get attributes") .map(Result::unwrap) } + /// Get the attribute value + pub fn attribute_value(&self, name: &str) -> Option> { + self.attribute(name).as_ref().map(Attribute::value) + } /// Dimensions for a variable pub fn dimensions(&self) -> &[Dimension] { &self.dimensions @@ -784,6 +788,23 @@ impl<'g> Variable<'g> { } /// Get multiple values from a variable + /// + /// Take notice: + /// `scale_factor` and `offset_factor` and other attributes are not + /// automatically applied. To take such into account, you can use code like below + /// ```rust,no_run + /// # use netcdf::attribute::AttrValue; + /// # let f = netcdf::create("file.nc")?; + /// # let var = f.variable("stuff").unwrap(); + /// // let var = ... + /// // let values = ... + /// if let Some(scale_offset) = var.attribute_value("scale_offset").transpose()? { + /// let scale_offset: f64 = scale_offset.try_into()?; + /// // values += scale_offset + /// } + /// # Result::<(), netcdf::error::Error>::Ok(()) + /// ``` + /// where `Option::transpose` is used to bubble up any read errors pub fn values(&self, extents: E) -> error::Result> where E: TryInto,