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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
use super::{core::driver::Driver, *};
use std::io::{self, Read};
/// Lazy encoded-byte reader over borrowed, complete resource slices.
#[derive(Debug)]
pub struct FramedEncoderReader<'c, 'input> {
driver: Driver<'c, 'input>,
deferred: Option<FramedEncodeError>,
failed: bool,
}
impl FramedCompressor {
/// Starts a lazy reader without encoding the input or performing I/O.
/// # Errors
/// Rejects forgotten sessions, unrepresentable aggregate lengths, or header allocation.
/// # Examples
/// ```
/// use mbrotli::framing::*;
/// use std::io::Read;
/// let mut encoder = FramedCompressor::new(Default::default())?;
/// let items = [FramedItem::Resource(FramedResource::from(&b"hello"[..]))];
/// let mut bytes = Vec::new();
/// encoder.framed_reader(items.as_slice().into(), Default::default())?
/// .read_to_end(&mut bytes)?;
/// assert_eq!(bytes, encoder.compress(items.as_slice().into())?);
/// # Ok::<(), Box<dyn std::error::Error>>(())
/// ```
pub fn framed_reader<'c, 'input>(
&'c mut self,
input: FramedInput<'input>,
stream: FramedEncodeStreamConfig,
) -> Result<FramedEncoderReader<'c, 'input>, FramedEncodeError> {
Driver::aggregate(input)?;
Ok(FramedEncoderReader {
driver: Driver::new(self.start(stream)?, input),
deferred: None,
failed: false,
})
}
}
impl<'input> FramedEncoderReader<'_, 'input> {
/// Cancels and returns the original description, without encoding or I/O.
pub fn into_inner(self) -> FramedInput<'input> {
self.driver.input
}
}
impl Read for FramedEncoderReader<'_, '_> {
fn read(&mut self, output: &mut [u8]) -> io::Result<usize> {
if output.is_empty() {
return Ok(0);
}
if let Some(error) = self.deferred.take() {
return Err(error.into());
}
if self.failed {
return Err(FramedEncodeError::InvalidState.into());
}
match self.driver.process(output) {
Ok(p) => Ok(p.produced),
Err(e) => {
self.failed = true;
if e.produced != 0 {
self.deferred = Some(e.error);
Ok(e.produced)
} else {
Err(e.error.into())
}
}
}
}
}