1use std::io::{self, Read};
24use lzma_sys::*;
25use std;
26use error::LzmaError;
27use ::Direction;
28use lzma_stream_wrapper::LzmaStreamWrapper;
29
30
31const DEFAULT_BUF_SIZE: usize = 4 * 1024;
32
33
34pub struct LzmaReader<T> {
35 inner: T,
36 stream: LzmaStreamWrapper,
37 buffer: Vec<u8>,
38 buffer_offset: usize,
39 buffer_len: usize,
40 direction: Direction,
41}
42
43
44impl<T: Read> LzmaReader<T> {
45 pub fn new_compressor(inner: T, preset: u32) -> Result<LzmaReader<T>, LzmaError> {
46 LzmaReader::with_capacity(DEFAULT_BUF_SIZE, inner, Direction::Compress, preset)
47 }
48
49 pub fn new_decompressor(inner: T) -> Result<LzmaReader<T>, LzmaError> {
50 LzmaReader::with_capacity(DEFAULT_BUF_SIZE, inner, Direction::Decompress, 0)
51 }
52
53 pub fn with_capacity(capacity: usize, inner: T, direction: Direction, preset: u32) -> Result<LzmaReader<T>, LzmaError> {
54 let mut reader = LzmaReader {
55 inner,
56 stream: LzmaStreamWrapper::new(),
57 buffer: vec![0; capacity],
58 buffer_offset: 0,
59 buffer_len: 0,
60 direction,
61 };
62
63 match reader.direction {
64 Direction::Compress => {
65 reader.stream.easy_encoder(preset, lzma_check::LzmaCheckCrc64)?
66 },
67 Direction::Decompress => {
68 reader.stream.stream_decoder(std::u64::MAX, 0)?
69 },
70 }
71
72 Ok(reader)
73 }
74
75 pub fn into_inner(self) -> T { self.inner }
76}
77
78
79impl<R: Read> Read for LzmaReader<R> {
80 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
83 if buf.is_empty() {
85 return Ok(0);
86 }
87
88 loop {
89 let mut action = lzma_action::LzmaRun;
90
91 if self.buffer_len == 0 {
93 self.buffer_offset = 0;
94 self.buffer_len = self.inner.read(&mut self.buffer)?;
95
96 if self.buffer_len == 0 {
97 action = lzma_action::LzmaFinish;
98 }
99 }
100
101 let result = self.stream.code(&self.buffer[self.buffer_offset..(self.buffer_offset+self.buffer_len)], buf, action);
103 self.buffer_offset += result.bytes_read;
104 self.buffer_len -= result.bytes_read;
105
106 let stream_end = match result.ret {
107 Ok(lzma_ret::LzmaStreamEnd) => true,
108 Ok(_) => false,
109 Err(err) => return Err(io::Error::new(io::ErrorKind::Other, err)),
110 };
111
112 if stream_end || result.bytes_written > 0 {
115 return Ok(result.bytes_written);
116 }
117 }
118 }
119}