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 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}