tiny_lz4_decoder_sys/
decoder.rs1use 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}