tiny_lz4_decoder_sys/
decoder.rs

1use crate::ffi::{
2    LZ4FDecompressionContext, LZ4F_createDecompressionContext, LZ4F_decompress,
3    LZ4F_freeDecompressionContext, LZ4_VERSION_NUMBER,
4};
5
6use std::io::{Error, ErrorKind, Read};
7
8const BUFFER_SIZE: usize = 32 * 1024;
9
10struct DecoderContext {
11    c: LZ4FDecompressionContext,
12}
13
14pub struct Decoder<R> {
15    c: DecoderContext,
16    r: R,
17    buf: Box<[u8]>,
18    pos: usize,
19    len: usize,
20    next: usize,
21}
22
23impl<R: Read> Decoder<R> {
24    pub fn new(r: R) -> Result<Decoder<R>, Error> {
25        Ok(Decoder {
26            r,
27            c: DecoderContext::new()?,
28            buf: vec![0; BUFFER_SIZE].into_boxed_slice(),
29            pos: BUFFER_SIZE,
30            len: BUFFER_SIZE,
31            next: 11,
32        })
33    }
34
35    pub fn reader(&self) -> &R {
36        &self.r
37    }
38
39    pub fn finish(self) -> (R, Result<(), Error>) {
40        (
41            self.r,
42            match self.next {
43                0 => Ok(()),
44                _ => Err(Error::new(
45                    ErrorKind::Interrupted,
46                    "`fn finish` can't be called before `fn reader`",
47                )),
48            },
49        )
50    }
51}
52
53impl<R: Read> Read for Decoder<R> {
54    fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
55        if self.next == 0 || buf.is_empty() {
56            return Ok(0);
57        }
58        let mut dst_offset: usize = 0;
59        while dst_offset == 0 {
60            if self.pos >= self.len {
61                let need = if self.buf.len() < self.next {
62                    self.buf.len()
63                } else {
64                    self.next
65                };
66                self.len = self.r.read(&mut self.buf[0..need])?;
67                if self.len == 0 {
68                    break;
69                }
70                self.pos = 0;
71                self.next -= self.len;
72            }
73            while (dst_offset < buf.len()) && (self.pos < self.len) {
74                let mut src_size = self.len - self.pos;
75                let mut dst_size = buf.len() - dst_offset;
76
77                let len = crate::ehandle::handle_error(unsafe {
78                    LZ4F_decompress(
79                        self.c.c,
80                        buf[dst_offset..].as_mut_ptr(),
81                        &mut dst_size,
82                        self.buf[self.pos..].as_ptr(),
83                        &mut src_size,
84                        std::ptr::null(),
85                    )
86                })?;
87
88                self.pos += src_size;
89                dst_offset += dst_size;
90
91                if len == 0 {
92                    self.next = 0;
93                    return Ok(dst_offset);
94                } else if self.next < len {
95                    self.next = len;
96                }
97            }
98        }
99
100        Ok(dst_offset)
101    }
102}
103
104impl DecoderContext {
105    fn new() -> Result<DecoderContext, Error> {
106        let mut context = LZ4FDecompressionContext(std::ptr::null_mut());
107        crate::ehandle::handle_error(unsafe {
108            LZ4F_createDecompressionContext(&mut context, LZ4_VERSION_NUMBER)
109        })?;
110        Ok(DecoderContext { c: context })
111    }
112}
113
114impl Drop for DecoderContext {
115    fn drop(&mut self) {
116        unsafe { LZ4F_freeDecompressionContext(self.c) };
117    }
118}