๐Ÿ“ฆ sharkdp / binocle

๐Ÿ“„ datatype.rs ยท 116 lines
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),
        }
    }
}