aboutsummaryrefslogtreecommitdiff
path: root/utils/src/read_ext.rs
blob: 7695adab5bdd55e82fe6728f16d09a2557c71993 (plain)
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
use std::convert::TryInto;

pub trait ReadExt {
    fn read_exact(&mut self, n: usize) -> Option<&[u8]>;

    fn read_le_i32(&mut self) -> Option<i32> {
        self.read_exact(4).map(|bytes| i32::from_le_bytes(bytes.try_into().unwrap()))
    }

    fn read_le_u32(&mut self) -> Option<u32> {
        self.read_exact(4).map(|bytes| u32::from_le_bytes(bytes.try_into().unwrap()))
    }

    fn read_le_u64(&mut self) -> Option<u64> {
        self.read_exact(8).map(|bytes| u64::from_le_bytes(bytes.try_into().unwrap()))
    }

    fn read_pascal_blob(&mut self) -> Option<&[u8]> {
        let len = self.read_le_u64()?;
        self.read_exact(len as usize)
    }

    fn read_pascal_string(&mut self) -> Option<Result<String, std::string::FromUtf8Error>> {
        self.read_pascal_blob().map(|b| String::from_utf8(b.to_vec()))
    }
}

impl ReadExt for &[u8] {
    fn read_exact(&mut self, n: usize) -> Option<&[u8]> {
        if self.len() >= n {
            let (res, newlist) = self.split_at(n);
            *self = newlist;
            Some(res)
        } else {
            None
        }
    }
}