mirror of
https://github.com/georust/netcdf.git
synced 2026-02-01 16:00:02 +00:00
support multi-valued attributes
This commit is contained in:
parent
6d8e9a0a04
commit
f022644854
640
src/attribute.rs
640
src/attribute.rs
@ -16,10 +16,6 @@ pub struct Attribute<'a> {
|
||||
pub(crate) ncid: nc_type,
|
||||
/// Variable/global this id is connected to
|
||||
pub(crate) varid: nc_type,
|
||||
/// Attribute type
|
||||
pub(crate) atttype: nc_type,
|
||||
/// Vector length
|
||||
pub(crate) attlen: nc_type,
|
||||
/// Holds the variable/group to prevent the
|
||||
/// attribute being deleted or modified
|
||||
pub(crate) _marker: PhantomData<&'a nc_type>,
|
||||
@ -34,9 +30,7 @@ impl<'a> std::fmt::Debug for Attribute<'a> {
|
||||
write!(f, "<<not utf8 name>>")?;
|
||||
}
|
||||
write!(f, "ncid: {}", self.ncid)?;
|
||||
write!(f, "varid: {}", self.varid)?;
|
||||
write!(f, "atttype: {}", self.atttype)?;
|
||||
write!(f, "attlen: {}", self.attlen)
|
||||
write!(f, "varid: {}", self.varid)
|
||||
}
|
||||
}
|
||||
|
||||
@ -53,152 +47,305 @@ impl<'a> Attribute<'a> {
|
||||
.unwrap_or(self.name.len());
|
||||
std::str::from_utf8(&self.name[..zeropos])
|
||||
}
|
||||
/// Get the value of the attribute
|
||||
#[allow(clippy::too_many_lines)]
|
||||
pub fn value(&self) -> error::Result<AttrValue> {
|
||||
let mut typ = 0;
|
||||
fn num_elems(&self) -> error::Result<usize> {
|
||||
let _l = LOCK.lock().unwrap();
|
||||
let mut nelems = 0;
|
||||
unsafe {
|
||||
error::checked(nc_inq_attlen(
|
||||
self.ncid,
|
||||
self.varid,
|
||||
self.name.as_ptr() as *const _,
|
||||
&mut nelems,
|
||||
))?;
|
||||
}
|
||||
Ok(nelems as _)
|
||||
}
|
||||
fn typ(&self) -> error::Result<nc_type> {
|
||||
let _l = LOCK.lock().unwrap();
|
||||
let mut atttype = 0;
|
||||
unsafe {
|
||||
error::checked(nc_inq_atttype(
|
||||
self.ncid,
|
||||
self.varid,
|
||||
self.name.as_ptr() as *const _,
|
||||
&mut typ,
|
||||
&mut atttype,
|
||||
))?;
|
||||
}
|
||||
Ok(atttype)
|
||||
}
|
||||
/// Get the value of the attribute
|
||||
#[allow(clippy::too_many_lines)]
|
||||
pub fn value(&self) -> error::Result<AttrValue> {
|
||||
let attlen = self.num_elems()?;
|
||||
let typ = self.typ()?;
|
||||
let _l = LOCK.lock().unwrap();
|
||||
|
||||
match typ {
|
||||
NC_UBYTE => {
|
||||
let mut value = 0;
|
||||
unsafe {
|
||||
error::checked(nc_get_att_uchar(
|
||||
self.ncid,
|
||||
self.varid,
|
||||
self.name.as_ptr() as *const _,
|
||||
&mut value,
|
||||
))?;
|
||||
NC_UBYTE => match attlen {
|
||||
1 => {
|
||||
let mut value = 0;
|
||||
unsafe {
|
||||
error::checked(nc_get_att_uchar(
|
||||
self.ncid,
|
||||
self.varid,
|
||||
self.name.as_ptr() as *const _,
|
||||
&mut value,
|
||||
))?;
|
||||
}
|
||||
Ok(AttrValue::Uchar(value))
|
||||
}
|
||||
Ok(AttrValue::Uchar(value))
|
||||
}
|
||||
NC_BYTE => {
|
||||
let mut value = 0;
|
||||
unsafe {
|
||||
error::checked(nc_get_att_schar(
|
||||
self.ncid,
|
||||
self.varid,
|
||||
self.name.as_ptr() as *const _,
|
||||
&mut value,
|
||||
))?;
|
||||
len => {
|
||||
let mut values = vec![0_u8; len as usize];
|
||||
unsafe {
|
||||
error::checked(nc_get_att_uchar(
|
||||
self.ncid,
|
||||
self.varid,
|
||||
self.name.as_ptr() as *const _,
|
||||
values.as_mut_ptr(),
|
||||
))?;
|
||||
}
|
||||
Ok(AttrValue::Uchars(values))
|
||||
}
|
||||
Ok(AttrValue::Schar(value))
|
||||
}
|
||||
NC_SHORT => {
|
||||
let mut value = 0;
|
||||
unsafe {
|
||||
error::checked(nc_get_att_short(
|
||||
self.ncid,
|
||||
self.varid,
|
||||
self.name.as_ptr() as *const _,
|
||||
&mut value,
|
||||
))?;
|
||||
},
|
||||
NC_BYTE => match attlen {
|
||||
1 => {
|
||||
let mut value = 0;
|
||||
unsafe {
|
||||
error::checked(nc_get_att_schar(
|
||||
self.ncid,
|
||||
self.varid,
|
||||
self.name.as_ptr() as *const _,
|
||||
&mut value,
|
||||
))?;
|
||||
}
|
||||
Ok(AttrValue::Schar(value))
|
||||
}
|
||||
Ok(AttrValue::Short(value))
|
||||
}
|
||||
NC_USHORT => {
|
||||
let mut value = 0;
|
||||
unsafe {
|
||||
error::checked(nc_get_att_ushort(
|
||||
self.ncid,
|
||||
self.varid,
|
||||
self.name.as_ptr() as *const _,
|
||||
&mut value,
|
||||
))?;
|
||||
len => {
|
||||
let mut values = vec![0; len as _];
|
||||
unsafe {
|
||||
error::checked(nc_get_att_schar(
|
||||
self.ncid,
|
||||
self.varid,
|
||||
self.name.as_ptr() as *const _,
|
||||
values.as_mut_ptr(),
|
||||
))?;
|
||||
}
|
||||
Ok(AttrValue::Schars(values))
|
||||
}
|
||||
Ok(AttrValue::Ushort(value))
|
||||
}
|
||||
NC_INT => {
|
||||
let mut value = 0;
|
||||
unsafe {
|
||||
error::checked(nc_get_att_int(
|
||||
self.ncid,
|
||||
self.varid,
|
||||
self.name.as_ptr() as *const _,
|
||||
&mut value,
|
||||
))?;
|
||||
},
|
||||
NC_SHORT => match attlen {
|
||||
1 => {
|
||||
let mut value = 0;
|
||||
unsafe {
|
||||
error::checked(nc_get_att_short(
|
||||
self.ncid,
|
||||
self.varid,
|
||||
self.name.as_ptr() as *const _,
|
||||
&mut value,
|
||||
))?;
|
||||
}
|
||||
Ok(AttrValue::Short(value))
|
||||
}
|
||||
Ok(AttrValue::Int(value))
|
||||
}
|
||||
NC_UINT => {
|
||||
let mut value = 0;
|
||||
unsafe {
|
||||
error::checked(nc_get_att_uint(
|
||||
self.ncid,
|
||||
self.varid,
|
||||
self.name.as_ptr() as *const _,
|
||||
&mut value,
|
||||
))?;
|
||||
len => {
|
||||
let mut values = vec![0; len as _];
|
||||
unsafe {
|
||||
error::checked(nc_get_att_short(
|
||||
self.ncid,
|
||||
self.varid,
|
||||
self.name.as_ptr() as *const _,
|
||||
values.as_mut_ptr(),
|
||||
))?;
|
||||
}
|
||||
Ok(AttrValue::Shorts(values))
|
||||
}
|
||||
Ok(AttrValue::Uint(value))
|
||||
}
|
||||
NC_INT64 => {
|
||||
let mut value = 0;
|
||||
unsafe {
|
||||
error::checked(nc_get_att_longlong(
|
||||
self.ncid,
|
||||
self.varid,
|
||||
self.name.as_ptr() as *const _,
|
||||
&mut value,
|
||||
))?;
|
||||
},
|
||||
NC_USHORT => match attlen {
|
||||
1 => {
|
||||
let mut value = 0;
|
||||
unsafe {
|
||||
error::checked(nc_get_att_ushort(
|
||||
self.ncid,
|
||||
self.varid,
|
||||
self.name.as_ptr() as *const _,
|
||||
&mut value,
|
||||
))?;
|
||||
}
|
||||
Ok(AttrValue::Ushort(value))
|
||||
}
|
||||
Ok(AttrValue::Longlong(value))
|
||||
}
|
||||
NC_UINT64 => {
|
||||
let mut value = 0;
|
||||
unsafe {
|
||||
error::checked(nc_get_att_ulonglong(
|
||||
self.ncid,
|
||||
self.varid,
|
||||
self.name.as_ptr() as *const _,
|
||||
&mut value,
|
||||
))?;
|
||||
len => {
|
||||
let mut values = vec![0; len as _];
|
||||
unsafe {
|
||||
error::checked(nc_get_att_ushort(
|
||||
self.ncid,
|
||||
self.varid,
|
||||
self.name.as_ptr() as *const _,
|
||||
values.as_mut_ptr(),
|
||||
))?;
|
||||
}
|
||||
Ok(AttrValue::Ushorts(values))
|
||||
}
|
||||
Ok(AttrValue::Ulonglong(value))
|
||||
}
|
||||
NC_FLOAT => {
|
||||
let mut value = 0.0;
|
||||
unsafe {
|
||||
error::checked(nc_get_att_float(
|
||||
self.ncid,
|
||||
self.varid,
|
||||
self.name.as_ptr() as *const _,
|
||||
&mut value,
|
||||
))?;
|
||||
},
|
||||
NC_INT => match attlen {
|
||||
1 => {
|
||||
let mut value = 0;
|
||||
unsafe {
|
||||
error::checked(nc_get_att_int(
|
||||
self.ncid,
|
||||
self.varid,
|
||||
self.name.as_ptr() as *const _,
|
||||
&mut value,
|
||||
))?;
|
||||
}
|
||||
Ok(AttrValue::Int(value))
|
||||
}
|
||||
Ok(AttrValue::Float(value))
|
||||
}
|
||||
NC_DOUBLE => {
|
||||
let mut value = 0.0;
|
||||
unsafe {
|
||||
error::checked(nc_get_att_double(
|
||||
self.ncid,
|
||||
self.varid,
|
||||
self.name.as_ptr() as *const _,
|
||||
&mut value,
|
||||
))?;
|
||||
len => {
|
||||
let mut values = vec![0; len as _];
|
||||
unsafe {
|
||||
error::checked(nc_get_att_int(
|
||||
self.ncid,
|
||||
self.varid,
|
||||
self.name.as_ptr() as *const _,
|
||||
values.as_mut_ptr(),
|
||||
))?;
|
||||
}
|
||||
Ok(AttrValue::Ints(values))
|
||||
}
|
||||
Ok(AttrValue::Double(value))
|
||||
}
|
||||
},
|
||||
NC_UINT => match attlen {
|
||||
1 => {
|
||||
let mut value = 0;
|
||||
unsafe {
|
||||
error::checked(nc_get_att_uint(
|
||||
self.ncid,
|
||||
self.varid,
|
||||
self.name.as_ptr() as *const _,
|
||||
&mut value,
|
||||
))?;
|
||||
}
|
||||
Ok(AttrValue::Uint(value))
|
||||
}
|
||||
len => {
|
||||
let mut values = vec![0; len as _];
|
||||
unsafe {
|
||||
error::checked(nc_get_att_uint(
|
||||
self.ncid,
|
||||
self.varid,
|
||||
self.name.as_ptr() as *const _,
|
||||
values.as_mut_ptr(),
|
||||
))?;
|
||||
}
|
||||
Ok(AttrValue::Uints(values))
|
||||
}
|
||||
},
|
||||
NC_INT64 => match attlen {
|
||||
1 => {
|
||||
let mut value = 0;
|
||||
unsafe {
|
||||
error::checked(nc_get_att_longlong(
|
||||
self.ncid,
|
||||
self.varid,
|
||||
self.name.as_ptr() as *const _,
|
||||
&mut value,
|
||||
))?;
|
||||
}
|
||||
Ok(AttrValue::Longlong(value))
|
||||
}
|
||||
len => {
|
||||
let mut values = vec![0; len as _];
|
||||
unsafe {
|
||||
error::checked(nc_get_att_longlong(
|
||||
self.ncid,
|
||||
self.varid,
|
||||
self.name.as_ptr() as *const _,
|
||||
values.as_mut_ptr(),
|
||||
))?;
|
||||
}
|
||||
|
||||
Ok(AttrValue::Longlongs(values))
|
||||
}
|
||||
},
|
||||
NC_UINT64 => match attlen {
|
||||
1 => {
|
||||
let mut value = 0;
|
||||
unsafe {
|
||||
error::checked(nc_get_att_ulonglong(
|
||||
self.ncid,
|
||||
self.varid,
|
||||
self.name.as_ptr() as *const _,
|
||||
&mut value,
|
||||
))?;
|
||||
}
|
||||
Ok(AttrValue::Ulonglong(value))
|
||||
}
|
||||
len => {
|
||||
let mut values = vec![0; len as _];
|
||||
unsafe {
|
||||
error::checked(nc_get_att_ulonglong(
|
||||
self.ncid,
|
||||
self.varid,
|
||||
self.name.as_ptr() as *const _,
|
||||
values.as_mut_ptr(),
|
||||
))?;
|
||||
}
|
||||
|
||||
Ok(AttrValue::Ulonglongs(values))
|
||||
}
|
||||
},
|
||||
NC_FLOAT => match attlen {
|
||||
1 => {
|
||||
let mut value = 0.0;
|
||||
unsafe {
|
||||
error::checked(nc_get_att_float(
|
||||
self.ncid,
|
||||
self.varid,
|
||||
self.name.as_ptr() as *const _,
|
||||
&mut value,
|
||||
))?;
|
||||
}
|
||||
Ok(AttrValue::Float(value))
|
||||
}
|
||||
len => {
|
||||
let mut values = vec![0.0; len as _];
|
||||
unsafe {
|
||||
error::checked(nc_get_att_float(
|
||||
self.ncid,
|
||||
self.varid,
|
||||
self.name.as_ptr() as *const _,
|
||||
values.as_mut_ptr(),
|
||||
))?;
|
||||
}
|
||||
Ok(AttrValue::Floats(values))
|
||||
}
|
||||
},
|
||||
NC_DOUBLE => match attlen {
|
||||
1 => {
|
||||
let mut value = 0.0;
|
||||
unsafe {
|
||||
error::checked(nc_get_att_double(
|
||||
self.ncid,
|
||||
self.varid,
|
||||
self.name.as_ptr() as *const _,
|
||||
&mut value,
|
||||
))?;
|
||||
}
|
||||
Ok(AttrValue::Double(value))
|
||||
}
|
||||
len => {
|
||||
let mut values = vec![0.0; len as _];
|
||||
unsafe {
|
||||
error::checked(nc_get_att_double(
|
||||
self.ncid,
|
||||
self.varid,
|
||||
self.name.as_ptr() as *const _,
|
||||
values.as_mut_ptr(),
|
||||
))?;
|
||||
}
|
||||
Ok(AttrValue::Doubles(values))
|
||||
}
|
||||
},
|
||||
NC_CHAR => {
|
||||
let mut lentext = 0;
|
||||
unsafe {
|
||||
error::checked(nc_inq_attlen(
|
||||
self.ncid,
|
||||
self.varid,
|
||||
self.name.as_ptr() as *const _,
|
||||
&mut lentext,
|
||||
))?;
|
||||
}
|
||||
let mut buf: Vec<u8> = vec![0; lentext];
|
||||
let lentext = attlen;
|
||||
let mut buf: Vec<u8> = vec![0; lentext as _];
|
||||
unsafe {
|
||||
error::checked(nc_get_att_text(
|
||||
self.ncid,
|
||||
@ -268,35 +415,11 @@ impl<'a> Iterator for AttributeIterator<'a> {
|
||||
return Some(Err(e));
|
||||
}
|
||||
}
|
||||
let mut atttype = 0;
|
||||
unsafe {
|
||||
if let Err(e) = error::checked(nc_inq_atttype(
|
||||
self.ncid,
|
||||
self.varid.unwrap_or(NC_GLOBAL),
|
||||
name.as_ptr() as *const _,
|
||||
&mut atttype,
|
||||
)) {
|
||||
return Some(Err(e));
|
||||
}
|
||||
}
|
||||
let mut attlen = 0;
|
||||
unsafe {
|
||||
if let Err(e) = error::checked(nc_inq_attlen(
|
||||
self.ncid,
|
||||
self.varid.unwrap_or(NC_GLOBAL),
|
||||
name.as_ptr() as *const _,
|
||||
&mut attlen,
|
||||
)) {
|
||||
return Some(Err(e));
|
||||
}
|
||||
}
|
||||
|
||||
let att = Attribute {
|
||||
name,
|
||||
ncid: self.ncid,
|
||||
varid: self.varid.unwrap_or(NC_GLOBAL),
|
||||
attlen: attlen as _,
|
||||
atttype,
|
||||
_marker: PhantomData,
|
||||
};
|
||||
|
||||
@ -311,15 +434,25 @@ impl<'a> Iterator for AttributeIterator<'a> {
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum AttrValue {
|
||||
Uchar(u8),
|
||||
Uchars(Vec<u8>),
|
||||
Schar(i8),
|
||||
Schars(Vec<i8>),
|
||||
Ushort(u16),
|
||||
Ushorts(Vec<u16>),
|
||||
Short(i16),
|
||||
Shorts(Vec<i16>),
|
||||
Uint(u32),
|
||||
Uints(Vec<u32>),
|
||||
Int(i32),
|
||||
Ints(Vec<i32>),
|
||||
Ulonglong(u64),
|
||||
Ulonglongs(Vec<u64>),
|
||||
Longlong(i64),
|
||||
Longlongs(Vec<i64>),
|
||||
Float(f32),
|
||||
Floats(Vec<f32>),
|
||||
Double(f64),
|
||||
Doubles(Vec<f64>),
|
||||
Str(String),
|
||||
}
|
||||
|
||||
@ -341,59 +474,125 @@ impl<'a> Attribute<'a> {
|
||||
};
|
||||
|
||||
let _l = LOCK.lock().unwrap();
|
||||
let atttype;
|
||||
error::checked(unsafe {
|
||||
match val {
|
||||
AttrValue::Uchar(x) => {
|
||||
atttype = NC_UBYTE;
|
||||
nc_put_att_uchar(ncid, varid, cname.as_ptr() as *const _, atttype, 1, &x)
|
||||
nc_put_att_uchar(ncid, varid, cname.as_ptr() as *const _, NC_UBYTE, 1, &x)
|
||||
}
|
||||
AttrValue::Uchars(x) => nc_put_att_uchar(
|
||||
ncid,
|
||||
varid,
|
||||
cname.as_ptr() as *const _,
|
||||
NC_UBYTE,
|
||||
x.len(),
|
||||
x.as_ptr(),
|
||||
),
|
||||
AttrValue::Schar(x) => {
|
||||
atttype = NC_BYTE;
|
||||
nc_put_att_schar(ncid, varid, cname.as_ptr() as *const _, atttype, 1, &x)
|
||||
nc_put_att_schar(ncid, varid, cname.as_ptr() as *const _, NC_BYTE, 1, &x)
|
||||
}
|
||||
AttrValue::Schars(x) => nc_put_att_schar(
|
||||
ncid,
|
||||
varid,
|
||||
cname.as_ptr() as *const _,
|
||||
NC_BYTE,
|
||||
x.len(),
|
||||
x.as_ptr(),
|
||||
),
|
||||
AttrValue::Ushort(x) => {
|
||||
atttype = NC_USHORT;
|
||||
nc_put_att_ushort(ncid, varid, cname.as_ptr() as *const _, atttype, 1, &x)
|
||||
nc_put_att_ushort(ncid, varid, cname.as_ptr() as *const _, NC_USHORT, 1, &x)
|
||||
}
|
||||
AttrValue::Ushorts(x) => nc_put_att_ushort(
|
||||
ncid,
|
||||
varid,
|
||||
cname.as_ptr() as *const _,
|
||||
NC_USHORT,
|
||||
x.len(),
|
||||
x.as_ptr(),
|
||||
),
|
||||
AttrValue::Short(x) => {
|
||||
atttype = NC_SHORT;
|
||||
nc_put_att_short(ncid, varid, cname.as_ptr() as *const _, atttype, 1, &x)
|
||||
nc_put_att_short(ncid, varid, cname.as_ptr() as *const _, NC_SHORT, 1, &x)
|
||||
}
|
||||
AttrValue::Shorts(x) => nc_put_att_short(
|
||||
ncid,
|
||||
varid,
|
||||
cname.as_ptr() as *const _,
|
||||
NC_SHORT,
|
||||
x.len(),
|
||||
x.as_ptr(),
|
||||
),
|
||||
AttrValue::Uint(x) => {
|
||||
atttype = NC_UINT;
|
||||
nc_put_att_uint(ncid, varid, cname.as_ptr() as *const _, atttype, 1, &x)
|
||||
nc_put_att_uint(ncid, varid, cname.as_ptr() as *const _, NC_UINT, 1, &x)
|
||||
}
|
||||
AttrValue::Uints(x) => nc_put_att_uint(
|
||||
ncid,
|
||||
varid,
|
||||
cname.as_ptr() as *const _,
|
||||
NC_UINT,
|
||||
x.len(),
|
||||
x.as_ptr(),
|
||||
),
|
||||
AttrValue::Int(x) => {
|
||||
atttype = NC_INT;
|
||||
nc_put_att_int(ncid, varid, cname.as_ptr() as *const _, atttype, 1, &x)
|
||||
nc_put_att_int(ncid, varid, cname.as_ptr() as *const _, NC_INT, 1, &x)
|
||||
}
|
||||
AttrValue::Ints(x) => nc_put_att_int(
|
||||
ncid,
|
||||
varid,
|
||||
cname.as_ptr() as *const _,
|
||||
NC_INT,
|
||||
x.len(),
|
||||
x.as_ptr(),
|
||||
),
|
||||
AttrValue::Ulonglong(x) => {
|
||||
atttype = NC_UINT64;
|
||||
nc_put_att_ulonglong(ncid, varid, cname.as_ptr() as *const _, atttype, 1, &x)
|
||||
nc_put_att_ulonglong(ncid, varid, cname.as_ptr() as *const _, NC_UINT64, 1, &x)
|
||||
}
|
||||
AttrValue::Ulonglongs(x) => nc_put_att_ulonglong(
|
||||
ncid,
|
||||
varid,
|
||||
cname.as_ptr() as *const _,
|
||||
NC_UINT64,
|
||||
x.len(),
|
||||
x.as_ptr(),
|
||||
),
|
||||
AttrValue::Longlong(x) => {
|
||||
atttype = NC_INT64;
|
||||
nc_put_att_longlong(ncid, varid, cname.as_ptr() as *const _, atttype, 1, &x)
|
||||
nc_put_att_longlong(ncid, varid, cname.as_ptr() as *const _, NC_INT64, 1, &x)
|
||||
}
|
||||
AttrValue::Longlongs(x) => nc_put_att_longlong(
|
||||
ncid,
|
||||
varid,
|
||||
cname.as_ptr() as *const _,
|
||||
NC_INT64,
|
||||
x.len(),
|
||||
x.as_ptr(),
|
||||
),
|
||||
AttrValue::Float(x) => {
|
||||
atttype = NC_FLOAT;
|
||||
nc_put_att_float(ncid, varid, cname.as_ptr() as *const _, atttype, 1, &x)
|
||||
nc_put_att_float(ncid, varid, cname.as_ptr() as *const _, NC_FLOAT, 1, &x)
|
||||
}
|
||||
AttrValue::Floats(x) => nc_put_att_float(
|
||||
ncid,
|
||||
varid,
|
||||
cname.as_ptr() as *const _,
|
||||
NC_FLOAT,
|
||||
x.len(),
|
||||
x.as_ptr(),
|
||||
),
|
||||
AttrValue::Double(x) => {
|
||||
atttype = NC_DOUBLE;
|
||||
nc_put_att_double(ncid, varid, cname.as_ptr() as *const _, atttype, 1, &x)
|
||||
}
|
||||
AttrValue::Str(ref x) => {
|
||||
atttype = NC_STRING;
|
||||
nc_put_att_text(
|
||||
ncid,
|
||||
varid,
|
||||
cname.as_ptr() as *const _,
|
||||
x.len(),
|
||||
x.as_ptr() as *const _,
|
||||
)
|
||||
nc_put_att_double(ncid, varid, cname.as_ptr() as *const _, NC_DOUBLE, 1, &x)
|
||||
}
|
||||
AttrValue::Doubles(x) => nc_put_att_double(
|
||||
ncid,
|
||||
varid,
|
||||
cname.as_ptr() as *const _,
|
||||
NC_DOUBLE,
|
||||
x.len(),
|
||||
x.as_ptr(),
|
||||
),
|
||||
AttrValue::Str(ref x) => nc_put_att_text(
|
||||
ncid,
|
||||
varid,
|
||||
cname.as_ptr() as *const _,
|
||||
x.len(),
|
||||
x.as_ptr() as *const _,
|
||||
),
|
||||
}
|
||||
})?;
|
||||
|
||||
@ -401,8 +600,6 @@ impl<'a> Attribute<'a> {
|
||||
name: cname,
|
||||
ncid,
|
||||
varid,
|
||||
atttype,
|
||||
attlen: 1,
|
||||
_marker: PhantomData,
|
||||
})
|
||||
}
|
||||
@ -421,16 +618,15 @@ impl<'a> Attribute<'a> {
|
||||
attname
|
||||
};
|
||||
let _l = LOCK.lock().unwrap();
|
||||
let e;
|
||||
let mut xtype = 0;
|
||||
unsafe {
|
||||
e = nc_inq_atttype(
|
||||
let e = unsafe {
|
||||
// Checking whether the variable exists by probing for its id
|
||||
nc_inq_attid(
|
||||
ncid,
|
||||
varid.unwrap_or(NC_GLOBAL),
|
||||
attname.as_ptr() as *const _,
|
||||
&mut xtype,
|
||||
);
|
||||
}
|
||||
std::ptr::null_mut(),
|
||||
)
|
||||
};
|
||||
if e == NC_ENOTATT {
|
||||
return Ok(None);
|
||||
}
|
||||
@ -449,8 +645,6 @@ impl<'a> Attribute<'a> {
|
||||
name: attname,
|
||||
ncid: ncid,
|
||||
varid: varid.unwrap_or(NC_GLOBAL),
|
||||
atttype: xtype,
|
||||
attlen: xlen as _,
|
||||
_marker: PhantomData,
|
||||
}))
|
||||
}
|
||||
@ -462,51 +656,101 @@ impl From<u8> for AttrValue {
|
||||
Self::Uchar(x)
|
||||
}
|
||||
}
|
||||
impl From<Vec<u8>> for AttrValue {
|
||||
fn from(x: Vec<u8>) -> Self {
|
||||
Self::Uchars(x)
|
||||
}
|
||||
}
|
||||
impl From<i8> for AttrValue {
|
||||
fn from(x: i8) -> Self {
|
||||
Self::Schar(x)
|
||||
}
|
||||
}
|
||||
impl From<Vec<i8>> for AttrValue {
|
||||
fn from(x: Vec<i8>) -> Self {
|
||||
Self::Schars(x)
|
||||
}
|
||||
}
|
||||
impl From<u16> for AttrValue {
|
||||
fn from(x: u16) -> Self {
|
||||
Self::Ushort(x)
|
||||
}
|
||||
}
|
||||
impl From<Vec<u16>> for AttrValue {
|
||||
fn from(x: Vec<u16>) -> Self {
|
||||
Self::Ushorts(x)
|
||||
}
|
||||
}
|
||||
impl From<i16> for AttrValue {
|
||||
fn from(x: i16) -> Self {
|
||||
Self::Short(x)
|
||||
}
|
||||
}
|
||||
impl From<Vec<i16>> for AttrValue {
|
||||
fn from(x: Vec<i16>) -> Self {
|
||||
Self::Shorts(x)
|
||||
}
|
||||
}
|
||||
impl From<u32> for AttrValue {
|
||||
fn from(x: u32) -> Self {
|
||||
Self::Uint(x)
|
||||
}
|
||||
}
|
||||
impl From<Vec<u32>> for AttrValue {
|
||||
fn from(x: Vec<u32>) -> Self {
|
||||
Self::Uints(x)
|
||||
}
|
||||
}
|
||||
impl From<i32> for AttrValue {
|
||||
fn from(x: i32) -> Self {
|
||||
Self::Int(x)
|
||||
}
|
||||
}
|
||||
impl From<Vec<i32>> for AttrValue {
|
||||
fn from(x: Vec<i32>) -> Self {
|
||||
Self::Ints(x)
|
||||
}
|
||||
}
|
||||
impl From<u64> for AttrValue {
|
||||
fn from(x: u64) -> Self {
|
||||
Self::Ulonglong(x)
|
||||
}
|
||||
}
|
||||
impl From<Vec<u64>> for AttrValue {
|
||||
fn from(x: Vec<u64>) -> Self {
|
||||
Self::Ulonglongs(x)
|
||||
}
|
||||
}
|
||||
impl From<i64> for AttrValue {
|
||||
fn from(x: i64) -> Self {
|
||||
Self::Longlong(x)
|
||||
}
|
||||
}
|
||||
impl From<Vec<i64>> for AttrValue {
|
||||
fn from(x: Vec<i64>) -> Self {
|
||||
Self::Longlongs(x)
|
||||
}
|
||||
}
|
||||
impl From<f32> for AttrValue {
|
||||
fn from(x: f32) -> Self {
|
||||
Self::Float(x)
|
||||
}
|
||||
}
|
||||
impl From<Vec<f32>> for AttrValue {
|
||||
fn from(x: Vec<f32>) -> Self {
|
||||
Self::Floats(x)
|
||||
}
|
||||
}
|
||||
impl From<f64> for AttrValue {
|
||||
fn from(x: f64) -> Self {
|
||||
Self::Double(x)
|
||||
}
|
||||
}
|
||||
impl From<Vec<f64>> for AttrValue {
|
||||
fn from(x: Vec<f64>) -> Self {
|
||||
Self::Doubles(x)
|
||||
}
|
||||
}
|
||||
impl From<&str> for AttrValue {
|
||||
fn from(x: &str) -> Self {
|
||||
Self::Str(x.to_string())
|
||||
|
||||
@ -276,3 +276,64 @@ fn all_attr_types() {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn multi_attributes() {
|
||||
let d = tempfile::tempdir().unwrap();
|
||||
let path = d.path().join("multi_attributes");
|
||||
{
|
||||
let mut file = netcdf::create(&path).unwrap();
|
||||
file.add_attribute("u8s", vec![1_u8, 2, 3, 4]).unwrap();
|
||||
file.add_attribute("i8s", vec![1_i8, 2, 3, 4]).unwrap();
|
||||
file.add_attribute("u16s", vec![1_u16, 2, 3, 4]).unwrap();
|
||||
file.add_attribute("i16s", vec![1_i16, 2, 3, 4]).unwrap();
|
||||
file.add_attribute("u32s", vec![1_u32, 2, 3, 4]).unwrap();
|
||||
file.add_attribute("i32s", vec![1_i32, 2, 3, 4]).unwrap();
|
||||
file.add_attribute("u64s", vec![1_u64, 2, 3, 4]).unwrap();
|
||||
file.add_attribute("i64s", vec![1_i64, 2, 3, 4]).unwrap();
|
||||
file.add_attribute("f32s", vec![1.0_f32, 2.0, 3.0, 4.0])
|
||||
.unwrap();
|
||||
file.add_attribute("f64s", vec![1.0_f64, 2.0, 3.0, 4.0])
|
||||
.unwrap();
|
||||
}
|
||||
let file = netcdf::open(path).unwrap();
|
||||
let mut atts = 0;
|
||||
for att in file.attributes().unwrap() {
|
||||
let att = att.unwrap();
|
||||
match att.name().unwrap() {
|
||||
"u8s" => {
|
||||
assert_eq!(att.value().unwrap(), vec![1_u8, 2, 3, 4].into());
|
||||
}
|
||||
"i8s" => {
|
||||
assert_eq!(att.value().unwrap(), vec![1_i8, 2, 3, 4].into());
|
||||
}
|
||||
"u16s" => {
|
||||
assert_eq!(att.value().unwrap(), vec![1_u16, 2, 3, 4].into());
|
||||
}
|
||||
"i16s" => {
|
||||
assert_eq!(att.value().unwrap(), vec![1_i16, 2, 3, 4].into());
|
||||
}
|
||||
"u32s" => {
|
||||
assert_eq!(att.value().unwrap(), vec![1_u32, 2, 3, 4].into());
|
||||
}
|
||||
"i32s" => {
|
||||
assert_eq!(att.value().unwrap(), vec![1_i32, 2, 3, 4].into());
|
||||
}
|
||||
"u64s" => {
|
||||
assert_eq!(att.value().unwrap(), vec![1_u64, 2, 3, 4].into());
|
||||
}
|
||||
"i64s" => {
|
||||
assert_eq!(att.value().unwrap(), vec![1_i64, 2, 3, 4].into());
|
||||
}
|
||||
"f32s" => {
|
||||
assert_eq!(att.value().unwrap(), vec![1.0_f32, 2.0, 3.0, 4.0].into());
|
||||
}
|
||||
"f64s" => {
|
||||
assert_eq!(att.value().unwrap(), vec![1.0_f64, 2.0, 3.0, 4.0].into());
|
||||
}
|
||||
name => panic!("{} not covered", name),
|
||||
}
|
||||
atts += 1;
|
||||
}
|
||||
assert_eq!(atts, 10);
|
||||
}
|
||||
|
||||
@ -5,4 +5,3 @@ pub(crate) fn test_location() -> std::path::PathBuf {
|
||||
let mnf_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| ".".into());
|
||||
Path::new(&mnf_dir).join("tests").join("testdata")
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user