Add back get_raw_values/get_raw_values_into

This commit is contained in:
Magnus Ulimoen 2024-08-09 17:05:53 +02:00
parent 9a8eb99688
commit 593fecdca3
4 changed files with 94 additions and 0 deletions

View File

@ -184,6 +184,34 @@ pub(crate) fn get_vars<T>(
get_vars_mono(var, tp, start, count, stride, values.cast())
}
/// Non-typechecked version of get_vars
/// to support getting a bag of bytes
pub fn get_raw_values_into(
variable: &crate::Variable,
buffer: &mut [u8],
extents: crate::Extents,
) -> crate::error::Result<()> {
let dims = variable.dimensions();
let (start, count, stride) = extents.get_start_count_stride(dims)?;
let number_of_elements = count.iter().copied().fold(1_usize, usize::saturating_mul);
let varsize = variable.vartype().size();
if number_of_elements * varsize != buffer.len() {
return Err("Buffer is not of requisite size".into());
}
checked_with_lock(|| unsafe {
netcdf_sys::nc_get_vars(
variable.ncid,
variable.varid,
start.as_ptr(),
count.as_ptr(),
stride.as_ptr(),
buffer.as_mut_ptr().cast(),
)
})?;
Ok(())
}
#[allow(clippy::too_many_lines)]
fn put_vars_mono(
var: &mut crate::VariableMut,

View File

@ -537,6 +537,42 @@ impl<'g> Variable<'g> {
let extents: Extents = extents.try_into().map_err(Into::into)?;
self.values_to_mono(buffer, &extents)
}
/// Fetches variable and returns the bytes.
/// It is up to the caller to decide what to do with these bytes,
/// including interpretation and freeing memory if
/// this is a vlen/string type
pub fn get_raw_values<E>(&self, extents: E) -> error::Result<Vec<u8>>
where
E: TryInto<Extents>,
E::Error: Into<error::Error>,
{
let extents: Extents = extents.try_into().map_err(Into::into)?;
let dims = self.dimensions();
let (_, count, _) = extents.get_start_count_stride(dims)?;
let number_of_elements = count.iter().copied().fold(1_usize, usize::saturating_mul);
let varsize = self.vartype().size();
let mut buffer = vec![0_u8; number_of_elements * varsize];
super::putget::get_raw_values_into(self, &mut buffer, extents)?;
Ok(buffer)
}
/// Fetches variable into provided buffer.
/// This functions returns bytes and it is up to the caller to
/// decide what to do with it, including freeing memory if
/// this is a vlen/string type
pub fn get_raw_values_into<E>(&self, buffer: &mut [u8], extents: E) -> error::Result<()>
where
E: TryInto<Extents>,
E::Error: Into<error::Error>,
{
let extents: Extents = extents.try_into().map_err(Into::into)?;
super::putget::get_raw_values_into(self, buffer, extents)?;
Ok(())
}
}
impl<'g> VariableMut<'g> {

View File

@ -1,4 +1,5 @@
/// Get location of the test files
#[allow(dead_code)]
pub(crate) fn test_location() -> std::path::PathBuf {
use std::path::Path;

View File

@ -1766,3 +1766,32 @@ fn close_file() {
let f = netcdf::open(path).unwrap();
f.close().unwrap();
}
#[test]
fn read_raw_values() {
let path = test_location().join("sfc_pres_temp.nc");
let file = netcdf::open(path).unwrap();
let var = file.variable("pressure").unwrap();
let d_lat = 6;
let d_lon = 12;
let buffer = var.get_raw_values(..).unwrap();
assert_eq!(buffer.len(), d_lat * d_lon * std::mem::size_of::<f32>());
let buffer = var.get_raw_values((0, ..)).unwrap();
assert_eq!(buffer.len(), 1 * d_lon * std::mem::size_of::<f32>());
let buffer = var.get_raw_values((.., 0)).unwrap();
assert_eq!(buffer.len(), d_lat * 1 * std::mem::size_of::<f32>());
let mut buffer = vec![0; d_lat * d_lon * std::mem::size_of::<f32>()];
var.get_raw_values_into(&mut buffer, ..).unwrap();
var.get_raw_values_into(&mut buffer[..d_lon * 1 * 4], (0, ..))
.unwrap();
// Mismatched buffers
var.get_raw_values_into(&mut buffer[..d_lon * 1 * 4 - 1], (0, ..))
.unwrap_err();
var.get_raw_values_into(&mut buffer[..d_lon * 1 * 4 + 1], (0, ..))
.unwrap_err();
}