use super::error::MatError;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MatClass {
Double,
Single,
Int8,
Int16,
Int32,
Int64,
UInt8,
UInt16,
UInt32,
UInt64,
Char,
Logical,
Struct,
Cell,
}
impl MatClass {
pub fn as_str(self) -> &'static str {
match self {
MatClass::Double => "double",
MatClass::Single => "single",
MatClass::Int8 => "int8",
MatClass::Int16 => "int16",
MatClass::Int32 => "int32",
MatClass::Int64 => "int64",
MatClass::UInt8 => "uint8",
MatClass::UInt16 => "uint16",
MatClass::UInt32 => "uint32",
MatClass::UInt64 => "uint64",
MatClass::Char => "char",
MatClass::Logical => "logical",
MatClass::Struct => "struct",
MatClass::Cell => "cell",
}
}
pub fn parse(s: &str) -> Result<Self, MatError> {
let trimmed = trim_null_padding(s);
Ok(match trimmed {
"double" => MatClass::Double,
"single" => MatClass::Single,
"int8" => MatClass::Int8,
"int16" => MatClass::Int16,
"int32" => MatClass::Int32,
"int64" => MatClass::Int64,
"uint8" => MatClass::UInt8,
"uint16" => MatClass::UInt16,
"uint32" => MatClass::UInt32,
"uint64" => MatClass::UInt64,
"char" => MatClass::Char,
"logical" => MatClass::Logical,
"struct" => MatClass::Struct,
"cell" => MatClass::Cell,
other => return Err(MatError::UnknownClass(other.to_string())),
})
}
pub fn elem_size(self) -> Option<usize> {
Some(match self {
MatClass::Double => 8,
MatClass::Single => 4,
MatClass::Int8 | MatClass::UInt8 | MatClass::Logical => 1,
MatClass::Int16 | MatClass::UInt16 | MatClass::Char => 2,
MatClass::Int32 | MatClass::UInt32 => 4,
MatClass::Int64 | MatClass::UInt64 => 8,
MatClass::Struct | MatClass::Cell => return None,
})
}
}
fn trim_null_padding(s: &str) -> &str {
s.trim_end_matches('\0').trim_end()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn roundtrip_class_strings() {
for c in [
MatClass::Double,
MatClass::Single,
MatClass::Int8,
MatClass::Int16,
MatClass::Int32,
MatClass::Int64,
MatClass::UInt8,
MatClass::UInt16,
MatClass::UInt32,
MatClass::UInt64,
MatClass::Char,
MatClass::Logical,
MatClass::Struct,
MatClass::Cell,
] {
assert_eq!(MatClass::parse(c.as_str()).unwrap(), c);
}
}
#[test]
fn parse_tolerates_null_padding() {
assert_eq!(MatClass::parse("double\0\0\0").unwrap(), MatClass::Double);
}
#[test]
fn unknown_class_is_error() {
assert!(matches!(MatClass::parse("datetime"), Err(MatError::UnknownClass(_))));
}
}