Skip to main content

comnum_spec/io/
raw.rs

1//! Raw interleaved samples of a [`Datatype`].
2
3use super::Datatype;
4use comnum_core::{Error, Result};
5use comnum_math::C64;
6use comnum_sim::loggers::create_parent_dir;
7use std::path::Path;
8
9pub(super) fn decode_all(bytes: &[u8], dt: Datatype) -> Result<Vec<C64>> {
10    let k = dt.sample_bytes();
11    if bytes.len() % k != 0 {
12        return Err(Error::Shape(format!("{} bytes is not a whole number of {} samples", bytes.len(), dt.name())));
13    }
14    Ok(bytes.chunks_exact(k).map(|b| dt.decode(b)).collect())
15}
16
17/// Read raw interleaved samples.
18///
19/// # Errors
20/// [`Error::Io`] if the file cannot be read, [`Error::Shape`] if its size is not a
21/// whole number of samples.
22pub fn read_raw(path: impl AsRef<Path>, datatype: Datatype) -> Result<Vec<C64>> {
23    decode_all(&std::fs::read(path)?, datatype)
24}
25
26/// Write raw interleaved samples (integer types are rounded and saturated).
27///
28/// # Errors
29/// [`Error::Io`].
30pub fn write_raw(path: impl AsRef<Path>, x: &[C64], datatype: Datatype) -> Result<()> {
31    write_creating_dirs(path.as_ref(), &encode_all(x, datatype))
32}
33
34pub(super) fn encode_all(x: &[C64], datatype: Datatype) -> Vec<u8> {
35    let mut out = Vec::with_capacity(x.len() * datatype.sample_bytes());
36    for &v in x {
37        datatype.encode(v, &mut out);
38    }
39    out
40}
41
42pub(super) fn write_creating_dirs(path: &Path, data: &[u8]) -> Result<()> {
43    create_parent_dir(path)?;
44    std::fs::write(path, data)?;
45    Ok(())
46}