Skip to main content

fallout_core/
reader.rs

1use std::io::{self, Read, Seek, SeekFrom};
2
3pub struct BigEndianReader<R> {
4    inner: R,
5}
6
7impl<R: Read + Seek> BigEndianReader<R> {
8    pub fn new(inner: R) -> Self {
9        Self { inner }
10    }
11
12    pub fn read_u8(&mut self) -> io::Result<u8> {
13        let mut buf = [0u8; 1];
14        self.inner.read_exact(&mut buf)?;
15        Ok(buf[0])
16    }
17
18    pub fn read_i16(&mut self) -> io::Result<i16> {
19        let mut buf = [0u8; 2];
20        self.inner.read_exact(&mut buf)?;
21        Ok(i16::from_be_bytes(buf))
22    }
23
24    pub fn read_i32(&mut self) -> io::Result<i32> {
25        let mut buf = [0u8; 4];
26        self.inner.read_exact(&mut buf)?;
27        Ok(i32::from_be_bytes(buf))
28    }
29
30    pub fn read_u32(&mut self) -> io::Result<u32> {
31        let mut buf = [0u8; 4];
32        self.inner.read_exact(&mut buf)?;
33        Ok(u32::from_be_bytes(buf))
34    }
35
36    pub fn read_f32(&mut self) -> io::Result<f32> {
37        let mut buf = [0u8; 4];
38        self.inner.read_exact(&mut buf)?;
39        Ok(f32::from_be_bytes(buf))
40    }
41
42    pub fn read_i32_array<const N: usize>(&mut self) -> io::Result<[i32; N]> {
43        let mut result = [0i32; N];
44        for item in &mut result {
45            *item = self.read_i32()?;
46        }
47        Ok(result)
48    }
49
50    pub fn read_i32_vec(&mut self, n: usize) -> io::Result<Vec<i32>> {
51        let mut result = Vec::with_capacity(n);
52        for _ in 0..n {
53            result.push(self.read_i32()?);
54        }
55        Ok(result)
56    }
57
58    pub fn read_fixed_string(&mut self, n: usize) -> io::Result<String> {
59        let bytes = self.read_bytes(n)?;
60        let end = bytes.iter().position(|&b| b == 0).unwrap_or(n);
61        String::from_utf8(bytes[..end].to_vec())
62            .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
63    }
64
65    pub fn read_bytes(&mut self, n: usize) -> io::Result<Vec<u8>> {
66        let mut buf = vec![0u8; n];
67        self.inner.read_exact(&mut buf)?;
68        Ok(buf)
69    }
70
71    /// Read a null-terminated string, consuming at most `max_len` bytes.
72    /// Stops at the first null byte but does NOT consume padding after it.
73    pub fn read_null_terminated_string(&mut self, max_len: usize) -> io::Result<String> {
74        let mut bytes = Vec::with_capacity(max_len);
75        for _ in 0..max_len {
76            let b = self.read_u8()?;
77            if b == 0 {
78                break;
79            }
80            bytes.push(b);
81        }
82        String::from_utf8(bytes).map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
83    }
84
85    pub fn skip(&mut self, n: u64) -> io::Result<()> {
86        self.inner.seek(SeekFrom::Current(n as i64))?;
87        Ok(())
88    }
89
90    pub fn position(&mut self) -> io::Result<u64> {
91        self.inner.stream_position()
92    }
93
94    pub fn seek_to(&mut self, pos: u64) -> io::Result<()> {
95        self.inner.seek(SeekFrom::Start(pos))?;
96        Ok(())
97    }
98
99    pub fn len(&mut self) -> io::Result<u64> {
100        let cur = self.position()?;
101        let end = self.inner.seek(SeekFrom::End(0))?;
102        self.inner.seek(SeekFrom::Start(cur))?;
103        Ok(end)
104    }
105
106    pub fn is_empty(&mut self) -> io::Result<bool> {
107        Ok(self.len()? == 0)
108    }
109}