matio_rs/
matfile.rs

1use crate::{MatioError, Result};
2use std::{fs, io, marker::PhantomData, ops::Deref, path::Path, ptr};
3
4/// Mat file
5pub struct MatFile<'a> {
6    pub(crate) mat_t: *mut ffi::mat_t,
7    marker: PhantomData<&'a ffi::mat_t>,
8}
9/// [Mat file](crate::MatFile) reader
10pub struct MatFileRead<'a>(MatFile<'a>);
11impl<'a> Deref for MatFileRead<'a> {
12    type Target = MatFile<'a>;
13    fn deref(&self) -> &Self::Target {
14        &self.0
15    }
16}
17impl<'a> MatFileRead<'a> {
18    /// Returns the list of variables within a [MatFile]
19    pub fn info(&self) {
20        let matvar_t = unsafe { ffi::Mat_VarReadNextInfo(self.mat_t) };
21        if !matvar_t.is_null() {
22            let name = unsafe { std::ffi::CStr::from_ptr((*matvar_t).name) };
23            let rank = unsafe { (*matvar_t).rank } as usize;
24            let mut dims: Vec<u64> = Vec::with_capacity(rank);
25            unsafe {
26                ptr::copy((*matvar_t).dims as *mut _, dims.as_mut_ptr(), rank);
27                dims.set_len(rank);
28            }
29            println!(
30                "Matlab var.: {:?} with dims: {:?}",
31                name.to_str().unwrap(),
32                dims
33            );
34            self.info();
35        }
36    }
37}
38/// [Mat file](crate::MatFile) writer
39pub struct MatFileWrite<'a>(MatFile<'a>);
40impl<'a> Deref for MatFileWrite<'a> {
41    type Target = MatFile<'a>;
42    fn deref(&self) -> &Self::Target {
43        &self.0
44    }
45}
46impl<'a> MatFile<'a> {
47    pub(crate) fn from_ptr(mat_t: *mut ffi::mat_t) -> MatFile<'a> {
48        MatFile {
49            mat_t,
50            marker: PhantomData,
51        }
52    }
53    /// Loads [Mat](crate::Mat) variables from a mat file
54    ///
55    /// ```
56    /// use matio_rs::MatFile;
57    /// # let file = tempfile::NamedTempFile::new().unwrap();
58    /// # let data_path = file.path();
59    /// let mat_file = MatFile::load(data_path)?;
60    /// # Ok::<(), matio_rs::MatioError>(())
61    /// ```
62    pub fn load<P: AsRef<Path>>(path: P) -> Result<MatFileRead<'a>> {
63        let attrs = fs::metadata(&path)?;
64        if attrs.is_file() {
65            let mat_name = std::ffi::CString::new(path.as_ref().to_str().unwrap())?;
66            let mat_t =
67                unsafe { ffi::Mat_Open(mat_name.as_ptr(), ffi::mat_acc_MAT_ACC_RDONLY as i32) };
68            if mat_t.is_null() {
69                Err(MatioError::MatOpen(
70                    path.as_ref().to_str().unwrap().to_string(),
71                ))
72            } else {
73                Ok(MatFileRead(MatFile::from_ptr(mat_t)))
74            }
75        } else {
76            Err(MatioError::NoFile(io::Error::new(
77                io::ErrorKind::NotFound,
78                format!("mat file {:?} not found", path.as_ref()),
79            )))
80        }
81    }
82    /// Saves [Mat](crate::Mat) variables to a mat file
83    ///
84    /// ```
85    /// use matio_rs::MatFile;
86    /// # let file = tempfile::NamedTempFile::new().unwrap();
87    /// # let data_path = file.path();
88    /// let mat_file = MatFile::save(data_path)?;
89    /// # Ok::<(), matio_rs::MatioError>(())
90    /// ```
91    pub fn save<P: AsRef<Path>>(path: P) -> Result<MatFileWrite<'a>> {
92        let mat_name = std::ffi::CString::new(path.as_ref().to_str().unwrap())?;
93        let mat_t =
94            unsafe { ffi::Mat_CreateVer(mat_name.as_ptr(), ptr::null(), ffi::mat_ft_MAT_FT_MAT5) };
95        if mat_t.is_null() {
96            Err(MatioError::MatOpen(
97                path.as_ref().to_str().unwrap().to_string(),
98            ))
99        } else {
100            Ok(MatFileWrite(MatFile::from_ptr(mat_t)))
101        }
102    }
103}
104
105impl<'a> Drop for MatFile<'a> {
106    fn drop(&mut self) {
107        if unsafe { ffi::Mat_Close(self.mat_t) } != 0 {
108            panic!("failed to close matfile")
109        }
110    }
111}