matrw 0.1.4

MAT-file serializing and deserializing
Documentation
use binrw::*;
use indexmap::IndexMap;

use super::variable7::MatVariable7;
use crate::interface::matfile::MatFile;

#[parser(reader, endian)]
pub fn parse_variable7() -> BinResult<IndexMap<String, MatVariable7>> {
    let mut map = IndexMap::new();

    loop {
        let data = match MatVariable7::read_options(reader, endian, ()) {
            Ok(d) => d,
            Err(err) if err.is_eof() => break,
            Err(err) => return Err(err),
        };

        let name = data.name();
        map.insert(name, data);
    }

    Ok(map)
}

#[binrw::writer(writer, endian)]
pub fn write_variable7(data: &IndexMap<String, MatVariable7>) -> BinResult<()> {
    for (_, val) in data.iter() {
        let _ = val.write_options(writer, endian, ());
    }

    Ok(())
}

#[binrw]
#[derive(Debug)]
pub struct MatFile7 {
    #[br(parse_with = parse_variable7)]
    #[bw(write_with = write_variable7)]
    pub data: IndexMap<String, MatVariable7>,
}

impl MatFile7 {
    pub fn new() -> Self {
        Self {
            data: IndexMap::new(),
        }
    }
}

impl Default for MatFile7 {
    fn default() -> Self {
        Self::new()
    }
}

impl From<MatFile> for MatFile7 {
    fn from(value: MatFile) -> Self {
        let mut matfile = MatFile7::new();

        for (key, val) in value.into_iter() {
            let mut val7: MatVariable7 = val.into();
            val7.set_name(&key);

            matfile.data.insert(key, val7);
        }

        matfile
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use binrw::BinReaderExt;
    use binrw::io::Cursor; // A no_std reimplementation of std::io // extension traits for use with readers and writers

    /// Binary representation of a mat file containing two variables 'a' and 'b'.
    /// To reproduce, in a MATLAB session with a clean workspace run
    /// `>> a = 42;`
    /// `>> b = pi;`
    /// `>> save('example.mat', 'a', 'b');`
    ///
    const MATFILE7: [u8; 222] = [
        0x4d, 0x41, 0x54, 0x4c, 0x41, 0x42, 0x20, 0x35, 0x2e, 0x30, 0x20, 0x4d, 0x41, 0x54, 0x2d, 0x66, 0x69,
        0x6c, 0x65, 0x2c, 0x20, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x3a, 0x20, 0x47, 0x4c, 0x4e,
        0x58, 0x41, 0x36, 0x34, 0x2c, 0x20, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x6f, 0x6e, 0x3a,
        0x20, 0x4d, 0x6f, 0x6e, 0x20, 0x4d, 0x61, 0x79, 0x20, 0x32, 0x30, 0x20, 0x31, 0x34, 0x3a, 0x31, 0x34,
        0x3a, 0x33, 0x39, 0x20, 0x32, 0x30, 0x32, 0x34, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
        0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
        0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x49, 0x4d, 0x0f, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
        0x78, 0x9c, 0xe3, 0x63, 0x60, 0x60, 0x30, 0x00, 0x62, 0x36, 0x20, 0xe6, 0x80, 0xd2, 0x20, 0xc0, 0x0a,
        0xe5, 0x33, 0xc2, 0x31, 0x23, 0x43, 0x22, 0x90, 0x66, 0x02, 0xd2, 0x5a, 0x40, 0x1a, 0x00, 0x17, 0x8c,
        0x00, 0xf2, 0x0f, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x78, 0x9c, 0xe3, 0x63, 0x60, 0x60, 0xb0,
        0x00, 0x62, 0x36, 0x20, 0xe6, 0x80, 0xd2, 0x20, 0xc0, 0x0a, 0xe5, 0x33, 0xc2, 0x31, 0x23, 0x43, 0x12,
        0x90, 0xe6, 0x84, 0x8a, 0x4b, 0xe8, 0xba, 0x84, 0xfc, 0x56, 0xe4, 0x74, 0x00, 0x00, 0x29, 0xb2, 0x03,
        0x21,
    ];

    #[test]
    fn parse_matfile7() {
        let data = Cursor::new(&MATFILE7[128..]).read_le::<MatFile7>().unwrap();
        println!("Deserialized data: {:#?}", data);
    }
    #[test]
    fn print_matfile7_varnames() {
        let matfile = Cursor::new(&MATFILE7[128..]).read_le::<MatFile7>().unwrap();
        println!("{:#?}", matfile.data.keys());
    }

    use std::fs::File;
    use std::io::{BufReader, Seek};

    #[test]
    #[ignore]
    fn parse_large_file_matfile7() {
        let f = File::open("tests/large.mat").unwrap();
        let mut reader = BufReader::new(f);
        let _ = reader.seek(std::io::SeekFrom::Current(128));
        reader.read_type::<MatFile7>(Endian::Little).unwrap();
    }
}