#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum FileEndian {
LittleEndian,
BigEndian,
}
impl FileEndian {
pub fn from_machst(machst: &[u8; 4]) -> Self {
Self::from_machst_with_info(machst).endian
}
pub fn from_machst_with_info(machst: &[u8; 4]) -> MachstInfo {
if machst[0] == 0x44 && machst[1] == 0x44 {
MachstInfo {
endian: FileEndian::LittleEndian,
is_standard: true,
description: "0x44 0x44 (little-endian)",
}
} else if machst[0] == 0x44 && machst[1] == 0x41 {
MachstInfo {
endian: FileEndian::LittleEndian,
is_standard: true,
description: "0x44 0x41 (little-endian, CCP4 variant)",
}
} else if machst[0] == 0x11 && machst[1] == 0x11 {
MachstInfo {
endian: FileEndian::BigEndian,
is_standard: true,
description: "0x11 0x11 (big-endian)",
}
} else {
MachstInfo {
endian: FileEndian::LittleEndian,
is_standard: false,
description: "non-standard (fallback to little-endian)",
}
}
}
pub fn to_machst(self) -> [u8; 4] {
match self {
FileEndian::LittleEndian => [0x44, 0x44, 0x00, 0x00],
FileEndian::BigEndian => [0x11, 0x11, 0x00, 0x00],
}
}
pub fn opposite(self) -> Self {
match self {
FileEndian::LittleEndian => FileEndian::BigEndian,
FileEndian::BigEndian => FileEndian::LittleEndian,
}
}
#[inline]
pub fn native() -> Self {
#[cfg(target_endian = "little")]
{
FileEndian::LittleEndian
}
#[cfg(target_endian = "big")]
{
FileEndian::BigEndian
}
}
#[inline]
pub fn is_native(self) -> bool {
self == Self::native()
}
}
#[doc(hidden)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct MachstInfo {
pub endian: FileEndian,
pub is_standard: bool,
pub description: &'static str,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_machst_le_standard() {
let info = FileEndian::from_machst_with_info(&[0x44, 0x44, 0x00, 0x00]);
assert_eq!(info.endian, FileEndian::LittleEndian);
assert!(info.is_standard);
}
#[test]
fn test_machst_le_ccp4_variant() {
let info = FileEndian::from_machst_with_info(&[0x44, 0x41, 0x00, 0x00]);
assert_eq!(info.endian, FileEndian::LittleEndian);
assert!(info.is_standard);
}
#[test]
fn test_machst_be_standard() {
let info = FileEndian::from_machst_with_info(&[0x11, 0x11, 0x00, 0x00]);
assert_eq!(info.endian, FileEndian::BigEndian);
assert!(info.is_standard);
}
#[test]
fn test_machst_non_standard_fallback() {
let info = FileEndian::from_machst_with_info(&[0xAB, 0xCD, 0x00, 0x00]);
assert_eq!(info.endian, FileEndian::LittleEndian);
assert!(!info.is_standard);
}
#[test]
fn test_opposite() {
assert_eq!(FileEndian::LittleEndian.opposite(), FileEndian::BigEndian);
assert_eq!(FileEndian::BigEndian.opposite(), FileEndian::LittleEndian);
}
}