1 /// The endianness for integer and floating-point numbers in SPSS system files.
3 /// SPSS system files can declare IBM 370 and DEC VAX floating-point
4 /// representations, but no file that uses either of these has ever been found
5 /// in the wild, so this code does not handle them.
6 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
8 /// Big-endian: MSB at lowest address.
11 /// Little-endian: LSB at lowest address.
16 pub fn identify_u32(expected_value: u32, bytes: [u8; 4]) -> Option<Self> {
17 let as_big: u32 = Endian::Big.parse(bytes);
18 let as_little: u32 = Endian::Little.parse(bytes);
19 match (as_big == expected_value, as_little == expected_value) {
20 (true, false) => Some(Endian::Big),
21 (false, true) => Some(Endian::Little),
26 pub fn identify_f64(expected_value: f64, bytes: [u8; 8]) -> Option<Self> {
27 let as_big: f64 = Endian::Big.parse(bytes);
28 let as_little: f64 = Endian::Little.parse(bytes);
29 match (as_big == expected_value, as_little == expected_value) {
30 (true, false) => Some(Endian::Big),
31 (false, true) => Some(Endian::Little),
37 pub trait ToBytes<T, const N: usize> {
38 fn to_bytes(self, value: T) -> [u8; N];
40 impl ToBytes<f64, 8> for Endian {
41 fn to_bytes(self, value: f64) -> [u8; 8] {
43 Endian::Big => f64::to_be_bytes(value),
44 Endian::Little => f64::to_le_bytes(value),
49 /// Parses an `N`-byte slice in one of the supported formats into native format
51 pub trait Parse<T, const N: usize> {
52 /// Given 'bytes', returns `T`.
53 fn parse(self, bytes: [u8; N]) -> T;
55 impl Parse<u64, 8> for Endian {
56 fn parse(self, bytes: [u8; 8]) -> u64 {
58 Endian::Big => u64::from_be_bytes(bytes),
59 Endian::Little => u64::from_le_bytes(bytes),
63 impl Parse<u32, 4> for Endian {
64 fn parse(self, bytes: [u8; 4]) -> u32 {
66 Endian::Big => u32::from_be_bytes(bytes),
67 Endian::Little => u32::from_le_bytes(bytes),
71 impl Parse<u16, 2> for Endian {
72 fn parse(self, bytes: [u8; 2]) -> u16 {
74 Endian::Big => u16::from_be_bytes(bytes),
75 Endian::Little => u16::from_le_bytes(bytes),
79 impl Parse<u8, 1> for Endian {
80 fn parse(self, bytes: [u8; 1]) -> u8 {
82 Endian::Big => u8::from_be_bytes(bytes),
83 Endian::Little => u8::from_le_bytes(bytes),
87 impl Parse<i64, 8> for Endian {
88 fn parse(self, bytes: [u8; 8]) -> i64 {
90 Endian::Big => i64::from_be_bytes(bytes),
91 Endian::Little => i64::from_le_bytes(bytes),
95 impl Parse<i32, 4> for Endian {
96 fn parse(self, bytes: [u8; 4]) -> i32 {
98 Endian::Big => i32::from_be_bytes(bytes),
99 Endian::Little => i32::from_le_bytes(bytes),
103 impl Parse<i16, 2> for Endian {
104 fn parse(self, bytes: [u8; 2]) -> i16 {
106 Endian::Big => i16::from_be_bytes(bytes),
107 Endian::Little => i16::from_le_bytes(bytes),
111 impl Parse<i8, 1> for Endian {
112 fn parse(self, bytes: [u8; 1]) -> i8 {
114 Endian::Big => i8::from_be_bytes(bytes),
115 Endian::Little => i8::from_le_bytes(bytes),
119 impl Parse<f64, 8> for Endian {
120 fn parse(self, bytes: [u8; 8]) -> f64 {
122 Endian::Big => f64::from_be_bytes(bytes),
123 Endian::Little => f64::from_le_bytes(bytes),