From 2c9e8015676ac516c0caa1ac0ae21af0a0853c6e Mon Sep 17 00:00:00 2001 From: Magnus Ulimoen Date: Fri, 6 Oct 2023 13:21:21 +0200 Subject: [PATCH 1/3] Bump netcdf-c to 4.9.2 --- .gitmodules | 4 ++-- netcdf-src/README.md | 2 +- netcdf-src/src/lib.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.gitmodules b/.gitmodules index ea1a16b..3a5a191 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,4 +1,4 @@ [submodule "netcdf-src/source"] path = netcdf-src/source - url = https://github.com/magnusuMET/netcdf-c.git - branch = bugfix/patched_v4.9.1_for_rust_netcdf + url = https://github.com/Unidata/netcdf-c.git + rev = 9328ba17cb53f13a63707547c94f4715243dafdf 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 From 857375dc9a4812698853d8b311c866c17fa96445 Mon Sep 17 00:00:00 2001 From: Magnus Ulimoen Date: Sat, 7 Oct 2023 19:24:54 +0200 Subject: [PATCH 2/3] Add TryFrom for AttrValue --- netcdf/src/attribute.rs | 180 +++++++++++++++++++++++++++++++++++++++- netcdf/src/group.rs | 4 + netcdf/src/variable.rs | 21 +++++ 3 files changed, 204 insertions(+), 1 deletion(-) 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, From 6b553ad6876d1717b31ad7ea392daac60c00c35a Mon Sep 17 00:00:00 2001 From: Magnus Ulimoen Date: Sun, 8 Oct 2023 09:58:07 +0200 Subject: [PATCH 3/3] Release new versions --- netcdf-src/Cargo.toml | 2 +- netcdf/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) 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/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 "