1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116use std::convert::TryInto;
#[derive(Clone, Copy, PartialEq)]
pub enum Endianness {
Big,
Little,
}
#[derive(Clone, Copy, PartialEq)]
pub enum Signedness {
Unsigned,
Signed,
}
#[derive(Clone)]
pub enum Datatype {
Integer8(Signedness),
Integer16(Signedness),
Integer32(Signedness),
Integer64(Signedness),
Float32,
Float64,
}
impl Datatype {
pub fn size(&self) -> usize {
match self {
Self::Integer8(_) => 1,
Self::Integer16(_) => 2,
Self::Integer32(_) => 4,
Self::Integer64(_) => 8,
Self::Float32 => 4,
Self::Float64 => 8,
}
}
pub fn read_as_float_from(&self, slice: &[u8], endianness: Endianness) -> Option<f32> {
// The 'slice.try_into().ok().map(โฆ)' repetition can not easily be removed, as we would
// need const generics because try_into() returns a '[u8, N]', depending on the size of
// the data type.
match (self, endianness) {
(Datatype::Integer8(Signedness::Unsigned), _) => slice
.try_into()
.ok()
.map(|bytes| u8::from_le_bytes(bytes) as f32),
(Datatype::Integer8(Signedness::Signed), _) => slice
.try_into()
.ok()
.map(|bytes| i8::from_le_bytes(bytes) as f32),
(Datatype::Integer16(Signedness::Unsigned), Endianness::Little) => slice
.try_into()
.ok()
.map(|bytes| u16::from_le_bytes(bytes) as f32),
(Datatype::Integer16(Signedness::Signed), Endianness::Little) => slice
.try_into()
.ok()
.map(|bytes| i16::from_le_bytes(bytes) as f32),
(Datatype::Integer16(Signedness::Unsigned), Endianness::Big) => slice
.try_into()
.ok()
.map(|bytes| u16::from_be_bytes(bytes) as f32),
(Datatype::Integer16(Signedness::Signed), Endianness::Big) => slice
.try_into()
.ok()
.map(|bytes| i16::from_be_bytes(bytes) as f32),
(Datatype::Integer32(Signedness::Unsigned), Endianness::Little) => slice
.try_into()
.ok()
.map(|bytes| u32::from_le_bytes(bytes) as f32),
(Datatype::Integer32(Signedness::Signed), Endianness::Little) => slice
.try_into()
.ok()
.map(|bytes| i32::from_le_bytes(bytes) as f32),
(Datatype::Integer32(Signedness::Unsigned), Endianness::Big) => slice
.try_into()
.ok()
.map(|bytes| u32::from_be_bytes(bytes) as f32),
(Datatype::Integer32(Signedness::Signed), Endianness::Big) => slice
.try_into()
.ok()
.map(|bytes| i32::from_be_bytes(bytes) as f32),
(Datatype::Integer64(Signedness::Unsigned), Endianness::Little) => slice
.try_into()
.ok()
.map(|bytes| u64::from_le_bytes(bytes) as f32),
(Datatype::Integer64(Signedness::Signed), Endianness::Little) => slice
.try_into()
.ok()
.map(|bytes| i64::from_le_bytes(bytes) as f32),
(Datatype::Integer64(Signedness::Unsigned), Endianness::Big) => slice
.try_into()
.ok()
.map(|bytes| u64::from_be_bytes(bytes) as f32),
(Datatype::Integer64(Signedness::Signed), Endianness::Big) => slice
.try_into()
.ok()
.map(|bytes| i64::from_be_bytes(bytes) as f32),
(Datatype::Float32, Endianness::Little) => {
slice.try_into().ok().map(f32::from_le_bytes)
}
(Datatype::Float32, Endianness::Big) => slice.try_into().ok().map(f32::from_be_bytes),
(Datatype::Float64, Endianness::Little) => slice
.try_into()
.ok()
.map(|bytes| f64::from_le_bytes(bytes) as f32),
(Datatype::Float64, Endianness::Big) => slice
.try_into()
.ok()
.map(|bytes| f64::from_be_bytes(bytes) as f32),
}
}
}