Skip to main content

libtw2_common/
io.rs

1use std::error;
2use std::fmt;
3use std::io;
4use std::io::Read;
5
6struct SeekOverflow(());
7
8pub fn seek_overflow() -> io::Error {
9    io::Error::new(io::ErrorKind::InvalidData, SeekOverflow(()))
10}
11
12impl fmt::Debug for SeekOverflow {
13    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
14        f.debug_struct("SeekOverflow").finish()
15    }
16}
17
18impl error::Error for SeekOverflow {}
19
20impl fmt::Display for SeekOverflow {
21    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
22        f.write_str("overflow while calculating seek offset")
23    }
24}
25
26pub trait ReadExt: Read {
27    fn read_retry(&mut self, buffer: &mut [u8]) -> io::Result<usize> {
28        let mut read = 0;
29        while read != buffer.len() {
30            match self.read(&mut buffer[read..]) {
31                Ok(0) => break,
32                Ok(r) => read += r,
33                Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
34                Err(e) => return Err(e),
35            }
36        }
37        Ok(read)
38    }
39}
40
41impl<T: Read> ReadExt for T {}
42
43pub trait FileExt {
44    fn read_offset_retry(&self, buffer: &mut [u8], offset: u64) -> io::Result<usize>;
45}
46
47#[cfg(feature = "file_offset")]
48impl FileExt for std::fs::File {
49    fn read_offset_retry(&self, buffer: &mut [u8], offset: u64) -> io::Result<usize> {
50        use crate::num::Cast;
51
52        // Make sure the additions in this function don't overflow
53        let _end_offset = offset
54            .checked_add(buffer.len().u64())
55            .ok_or_else(seek_overflow)?;
56
57        let mut read = 0;
58        while read != buffer.len() {
59            match file_offset::FileExt::read_offset(self, &mut buffer[read..], offset + read.u64())
60            {
61                Ok(0) => break,
62                Ok(r) => read += r,
63                Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
64                Err(e) => return Err(e),
65            }
66        }
67        Ok(read)
68    }
69}