1use core::fmt;
4
5use crate::error::{Error as Hdf5Error, FormatError};
6
7#[derive(Debug)]
16#[non_exhaustive]
17pub enum MatError {
18 Hdf5(Hdf5Error),
20 Format(FormatError),
22 Io(std::io::Error),
24 RootMustBeStruct,
26 UnsupportedType(&'static str),
28 MixedSequenceElementTypes,
30 RaggedMatrix {
32 expected: usize,
34 got: usize,
36 },
37 ShapeMismatch {
39 expected: String,
41 actual: String,
43 },
44 MissingField(String),
46 UnknownClass(String),
48 UnsupportedMatlabClass(String),
54 Utf16Decode(String),
56 Custom(String),
58}
59
60impl fmt::Display for MatError {
61 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
62 match self {
63 MatError::Hdf5(e) => write!(f, "HDF5 error: {e}"),
64 MatError::Format(e) => write!(f, "HDF5 format error: {e}"),
65 MatError::Io(e) => write!(f, "I/O error: {e}"),
66 MatError::RootMustBeStruct => write!(
67 f,
68 "top-level value must be a struct with named fields; each field becomes a MATLAB variable"
69 ),
70 MatError::UnsupportedType(t) => write!(f, "unsupported Rust type for MAT v7.3: {t}"),
71 MatError::MixedSequenceElementTypes => write!(
72 f,
73 "sequence elements have mixed primitive types; all elements of a numeric array must share a type"
74 ),
75 MatError::RaggedMatrix { expected, got } => write!(
76 f,
77 "ragged 2-D matrix: expected row length {expected}, got {got}"
78 ),
79 MatError::ShapeMismatch { expected, actual } => {
80 write!(f, "shape mismatch: expected {expected}, got {actual}")
81 }
82 MatError::MissingField(name) => write!(f, "missing required field: {name}"),
83 MatError::UnknownClass(c) => write!(f, "unknown MATLAB_class: {c:?}"),
84 MatError::UnsupportedMatlabClass(c) => write!(
85 f,
86 "MATLAB class {c:?} is not yet supported for reading (modern `string` is; \
87 other MCOS opaque classes such as datetime/categorical/table are refused for now)"
88 ),
89 MatError::Utf16Decode(msg) => write!(f, "UTF-16 decode: {msg}"),
90 MatError::Custom(msg) => write!(f, "{msg}"),
91 }
92 }
93}
94
95impl std::error::Error for MatError {
96 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
97 match self {
98 MatError::Hdf5(e) => Some(e),
99 MatError::Format(e) => Some(e),
100 MatError::Io(e) => Some(e),
101 _ => None,
102 }
103 }
104}
105
106impl From<Hdf5Error> for MatError {
107 fn from(e: Hdf5Error) -> Self {
108 MatError::Hdf5(e)
109 }
110}
111
112impl From<FormatError> for MatError {
113 fn from(e: FormatError) -> Self {
114 MatError::Format(e)
115 }
116}
117
118impl From<std::io::Error> for MatError {
119 fn from(e: std::io::Error) -> Self {
120 MatError::Io(e)
121 }
122}
123
124#[cfg(feature = "serde")]
125impl serde::ser::Error for MatError {
126 fn custom<T: fmt::Display>(msg: T) -> Self {
127 MatError::Custom(msg.to_string())
128 }
129}
130
131#[cfg(feature = "serde")]
132impl serde::de::Error for MatError {
133 fn custom<T: fmt::Display>(msg: T) -> Self {
134 MatError::Custom(msg.to_string())
135 }
136}