brotli_decompressor/
io_wrappers.rs

1#[cfg(feature="std")]
2use std::io::{self, ErrorKind, Read, Write};
3
4/// this trait does not allow for transient errors: they must be retried in the underlying layer
5pub trait CustomWrite<ErrType> {
6  fn write(self: &mut Self, data: &[u8]) -> Result<usize, ErrType>;
7  fn flush(self: &mut Self) -> Result<(), ErrType>;
8}
9/// this trait does not allow for transient errors: they must be retried in the underlying layer
10pub trait CustomRead<ErrType> {
11  fn read(self: &mut Self, data: &mut [u8]) -> Result<usize, ErrType>;
12}
13
14#[allow(dead_code)] // prefer to replace 2 inlines in BrotliDecompressCustomIo once traits work
15pub fn write_all<ErrType, OutputType>(w: &mut OutputType, buf: &[u8]) -> Result<(), ErrType>
16  where OutputType: CustomWrite<ErrType>
17{
18  let mut total_written: usize = 0;
19  while total_written < buf.len() {
20    match w.write(&buf[total_written..]) {
21      Err(e) => return Result::Err(e),
22      // CustomResult::Transient(e) => continue,
23      Ok(cur_written) => {
24        assert_eq!(cur_written == 0, false); // not allowed by the contract
25        total_written += cur_written;
26      }
27    }
28  }
29  Ok(())
30}
31
32#[cfg(feature="std")]
33pub struct IntoIoReader<InputType: Read>(pub InputType);
34
35#[cfg(feature="std")]
36pub struct IntoIoWriter<InputType: Write>(pub InputType);
37
38
39#[cfg(feature="std")]
40pub struct IoWriterWrapper<'a, OutputType: Write + 'a>(pub &'a mut OutputType);
41
42
43#[cfg(feature="std")]
44pub struct IoReaderWrapper<'a, OutputType: Read + 'a>(pub &'a mut OutputType);
45
46#[cfg(feature="std")]
47impl<'a, OutputType: Write> CustomWrite<io::Error> for IoWriterWrapper<'a, OutputType> {
48  fn write(self: &mut Self, buf: &[u8]) -> Result<usize, io::Error> {
49    loop {
50      match self.0.write(buf) {
51        Err(e) => {
52          match e.kind() {
53            ErrorKind::Interrupted => continue,
54            _ => return Err(e),
55          }
56        }
57        Ok(cur_written) => return Ok(cur_written),
58      }
59    }
60  }
61  fn flush(self: &mut Self) -> Result<(), io::Error> {
62    loop {
63      match self.0.flush() {
64        Err(e) => {
65          match e.kind() {
66            ErrorKind::Interrupted => continue,
67            _ => return Err(e),
68          }
69        }
70        Ok(_) => return Ok(()),
71      }
72    }
73  }
74}
75
76
77#[cfg(feature="std")]
78impl<'a, InputType: Read> CustomRead<io::Error> for IoReaderWrapper<'a, InputType> {
79  fn read(self: &mut Self, buf: &mut [u8]) -> Result<usize, io::Error> {
80    loop {
81      match self.0.read(buf) {
82        Err(e) => {
83          match e.kind() {
84            ErrorKind::Interrupted => continue,
85            _ => return Err(e),
86          }
87        }
88        Ok(cur_read) => return Ok(cur_read),
89      }
90    }
91  }
92}
93
94#[cfg(feature="std")]
95impl<InputType: Read> CustomRead<io::Error> for IntoIoReader<InputType> {
96  fn read(self: &mut Self, buf: &mut [u8]) -> Result<usize, io::Error> {
97    loop {
98      match self.0.read(buf) {
99        Err(e) => {
100          match e.kind() {
101            ErrorKind::Interrupted => continue,
102            _ => return Err(e),
103          }
104        }
105        Ok(cur_read) => return Ok(cur_read),
106      }
107    }
108  }
109}
110
111#[cfg(feature="std")]
112impl<InputType: Write> CustomWrite<io::Error> for IntoIoWriter<InputType> {
113  fn flush(self: &mut Self) -> Result<(), io::Error> {
114    loop {
115      match self.0.flush() {
116        Err(e) => {
117          match e.kind() {
118            ErrorKind::Interrupted => continue,
119            _ => return Err(e),
120          }
121        }
122        Ok(_) => return Ok(()),
123      }
124    }     
125  }
126  fn write(self: &mut Self, buf: &[u8]) -> Result<usize, io::Error> {
127    loop {
128      match self.0.write(buf) {
129        Err(e) => {
130          match e.kind() {
131            ErrorKind::Interrupted => continue,
132            _ => return Err(e),
133          }
134        }
135        Ok(cur_written) => return Ok(cur_written),
136      }
137    }
138  }
139}