/rust/registry/src/index.crates.io-1949cf8c6b5b557f/brotli-decompressor-5.0.0/src/reader.rs
Line | Count | Source |
1 | | #[cfg(feature="std")] |
2 | | use std::io::{self, Error, ErrorKind, Read}; |
3 | | #[cfg(feature="std")] |
4 | | pub use alloc_stdlib::StandardAlloc; |
5 | | #[cfg(all(feature="unsafe",feature="std"))] |
6 | | pub use alloc_stdlib::HeapAlloc; |
7 | | pub use huffman::{HuffmanCode, HuffmanTreeGroup}; |
8 | | pub use state::BrotliState; |
9 | | // use io_wrappers::write_all; |
10 | | pub use io_wrappers::{CustomRead, CustomWrite}; |
11 | | #[cfg(feature="std")] |
12 | | pub use io_wrappers::{IntoIoReader, IoReaderWrapper, IoWriterWrapper}; |
13 | | pub use super::decode::{BrotliDecompressStream, BrotliResult}; |
14 | | pub use alloc::{AllocatedStackMemory, Allocator, SliceWrapper, SliceWrapperMut, StackAllocator}; |
15 | | |
16 | | #[cfg(feature="std")] |
17 | | pub struct DecompressorCustomAlloc<R: Read, |
18 | | BufferType : SliceWrapperMut<u8>, |
19 | | AllocU8 : Allocator<u8>, |
20 | | AllocU32 : Allocator<u32>, |
21 | | AllocHC : Allocator<HuffmanCode> >(DecompressorCustomIo<io::Error, |
22 | | IntoIoReader<R>, |
23 | | BufferType, |
24 | | AllocU8, AllocU32, AllocHC>); |
25 | | |
26 | | |
27 | | #[cfg(feature="std")] |
28 | | impl<R: Read, |
29 | | BufferType : SliceWrapperMut<u8>, |
30 | | AllocU8, |
31 | | AllocU32, |
32 | | AllocHC> DecompressorCustomAlloc<R, BufferType, AllocU8, AllocU32, AllocHC> |
33 | | where AllocU8 : Allocator<u8>, AllocU32 : Allocator<u32>, AllocHC : Allocator<HuffmanCode> |
34 | | { |
35 | | |
36 | 0 | pub fn new(r: R, buffer : BufferType, |
37 | 0 | alloc_u8 : AllocU8, alloc_u32 : AllocU32, alloc_hc : AllocHC) -> Self { |
38 | 0 | DecompressorCustomAlloc::<R, BufferType, AllocU8, AllocU32, AllocHC>( |
39 | 0 | DecompressorCustomIo::<Error, |
40 | 0 | IntoIoReader<R>, |
41 | 0 | BufferType, |
42 | 0 | AllocU8, AllocU32, AllocHC>::new(IntoIoReader::<R>(r), |
43 | 0 | buffer, |
44 | 0 | alloc_u8, alloc_u32, alloc_hc, |
45 | 0 | Error::new(ErrorKind::InvalidData, |
46 | 0 | "Invalid Data"))) |
47 | 0 | } |
48 | | |
49 | 0 | pub fn new_with_custom_dictionary(r: R, buffer : BufferType, |
50 | 0 | alloc_u8 : AllocU8, alloc_u32 : AllocU32, alloc_hc : AllocHC, |
51 | 0 | dict: AllocU8::AllocatedMemory) -> Self { |
52 | 0 | DecompressorCustomAlloc::<R, BufferType, AllocU8, AllocU32, AllocHC>( |
53 | 0 | DecompressorCustomIo::<Error, |
54 | 0 | IntoIoReader<R>, |
55 | 0 | BufferType, |
56 | 0 | AllocU8, AllocU32, AllocHC>::new_with_custom_dictionary(IntoIoReader::<R>(r), |
57 | 0 | buffer, |
58 | 0 | alloc_u8, alloc_u32, alloc_hc, |
59 | 0 | dict, |
60 | 0 | Error::new(ErrorKind::InvalidData, |
61 | 0 | "Invalid Data"))) |
62 | 0 | } Unexecuted instantiation: <brotli_decompressor::reader::DecompressorCustomAlloc<&[u8], alloc_stdlib::heap_alloc::WrapBox<u8>, alloc_stdlib::std_alloc::StandardAlloc, alloc_stdlib::std_alloc::StandardAlloc, alloc_stdlib::std_alloc::StandardAlloc>>::new_with_custom_dictionary Unexecuted instantiation: <brotli_decompressor::reader::DecompressorCustomAlloc<_, _, _, _, _>>::new_with_custom_dictionary |
63 | | |
64 | 0 | pub fn get_ref(&self) -> &R { |
65 | 0 | &self.0.get_ref().0 |
66 | 0 | } |
67 | 0 | pub fn get_mut(&mut self) -> &mut R { |
68 | 0 | &mut self.0.get_mut().0 |
69 | 0 | } |
70 | 0 | pub fn into_inner(self) -> R { |
71 | 0 | self.0.into_inner().0 |
72 | 0 | } |
73 | | } |
74 | | #[cfg(feature="std")] |
75 | | impl<R: Read, |
76 | | BufferType : SliceWrapperMut<u8>, |
77 | | AllocU8 : Allocator<u8>, |
78 | | AllocU32 : Allocator<u32>, |
79 | | AllocHC : Allocator<HuffmanCode> > Read for DecompressorCustomAlloc<R, |
80 | | BufferType, |
81 | | AllocU8, |
82 | | AllocU32, |
83 | | AllocHC> { |
84 | 0 | fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> { |
85 | 0 | self.0.read(buf) |
86 | 0 | } Unexecuted instantiation: <brotli_decompressor::reader::DecompressorCustomAlloc<&[u8], alloc_stdlib::heap_alloc::WrapBox<u8>, alloc_stdlib::std_alloc::StandardAlloc, alloc_stdlib::std_alloc::StandardAlloc, alloc_stdlib::std_alloc::StandardAlloc> as std::io::Read>::read Unexecuted instantiation: <brotli_decompressor::reader::DecompressorCustomAlloc<_, _, _, _, _> as std::io::Read>::read |
87 | | } |
88 | | |
89 | | |
90 | | #[cfg(not(any(feature="unsafe", not(feature="std"))))] |
91 | | pub struct Decompressor<R: Read>(DecompressorCustomAlloc<R, |
92 | | <StandardAlloc |
93 | | as Allocator<u8>>::AllocatedMemory, |
94 | | StandardAlloc, |
95 | | StandardAlloc, |
96 | | StandardAlloc>); |
97 | | |
98 | | |
99 | | #[cfg(not(any(feature="unsafe", not(feature="std"))))] |
100 | | impl<R: Read> Decompressor<R> { |
101 | 0 | pub fn new(r: R, buffer_size: usize) -> Self { |
102 | 0 | let dict = <StandardAlloc as Allocator<u8>>::AllocatedMemory::default(); |
103 | 0 | Self::new_with_custom_dict(r, buffer_size, dict) |
104 | 0 | } Unexecuted instantiation: <brotli_decompressor::reader::Decompressor<&[u8]>>::new Unexecuted instantiation: <brotli_decompressor::reader::Decompressor<_>>::new |
105 | 0 | pub fn new_with_custom_dict(r: R, buffer_size: usize, dict: <StandardAlloc as Allocator<u8>>::AllocatedMemory) -> Self { |
106 | 0 | let mut alloc = StandardAlloc::default(); |
107 | 0 | let buffer = <StandardAlloc as Allocator<u8>>::alloc_cell(&mut alloc, if buffer_size == 0 {4096} else {buffer_size}); |
108 | 0 | Decompressor::<R>(DecompressorCustomAlloc::<R, |
109 | 0 | <StandardAlloc |
110 | 0 | as Allocator<u8>>::AllocatedMemory, |
111 | 0 | StandardAlloc, |
112 | 0 | StandardAlloc, |
113 | 0 | StandardAlloc>::new_with_custom_dictionary(r, |
114 | 0 | buffer, |
115 | 0 | alloc, |
116 | 0 | StandardAlloc::default(), |
117 | 0 | StandardAlloc::default(), |
118 | 0 | dict)) |
119 | 0 | } Unexecuted instantiation: <brotli_decompressor::reader::Decompressor<&[u8]>>::new_with_custom_dict Unexecuted instantiation: <brotli_decompressor::reader::Decompressor<_>>::new_with_custom_dict |
120 | | |
121 | 0 | pub fn get_ref(&self) -> &R { |
122 | 0 | &self.0.get_ref() |
123 | 0 | } |
124 | 0 | pub fn get_mut(&mut self) -> &mut R { |
125 | 0 | &mut ((self.0).0).get_mut().0 |
126 | 0 | } |
127 | 0 | pub fn into_inner(self) -> R { |
128 | 0 | self.0.into_inner() |
129 | 0 | } |
130 | | } |
131 | | |
132 | | |
133 | | #[cfg(all(feature="unsafe", feature="std"))] |
134 | | pub struct Decompressor<R: Read>(DecompressorCustomAlloc<R, |
135 | | <HeapAlloc<u8> |
136 | | as Allocator<u8>>::AllocatedMemory, |
137 | | HeapAlloc<u8>, |
138 | | HeapAlloc<u32>, |
139 | | HeapAlloc<HuffmanCode> >); |
140 | | |
141 | | |
142 | | #[cfg(all(feature="unsafe", feature="std"))] |
143 | | impl<R: Read> Decompressor<R> { |
144 | | pub fn new(r: R, buffer_size: usize) -> Self { |
145 | | let dict = <HeapAlloc<u8> as Allocator<u8>>::AllocatedMemory::default(); |
146 | | Self::new_with_custom_dictionary(r, buffer_size, dict) |
147 | | } |
148 | | pub fn new_with_custom_dictionary(r: R, buffer_size: usize, dict: <HeapAlloc<u8> |
149 | | as Allocator<u8>>::AllocatedMemory) -> Self { |
150 | | let mut alloc_u8 = HeapAlloc::<u8>::new(0); |
151 | | let buffer = alloc_u8.alloc_cell(if buffer_size == 0 {4096} else {buffer_size}); |
152 | | let alloc_u32 = HeapAlloc::<u32>::new(0); |
153 | | let alloc_hc = HeapAlloc::<HuffmanCode>::new(HuffmanCode{ |
154 | | bits:0, value: 0, |
155 | | }); |
156 | | Decompressor::<R>(DecompressorCustomAlloc::<R, |
157 | | <HeapAlloc<u8> |
158 | | as Allocator<u8>>::AllocatedMemory, |
159 | | HeapAlloc<u8>, |
160 | | HeapAlloc<u32>, |
161 | | HeapAlloc<HuffmanCode> > |
162 | | ::new_with_custom_dictionary(r, buffer, alloc_u8, alloc_u32, alloc_hc, dict)) |
163 | | } |
164 | | |
165 | | pub fn get_ref(&self) -> &R { |
166 | | self.0.get_ref() |
167 | | } |
168 | | pub fn get_mut(&mut self) -> &mut R { |
169 | | &mut (self.0).0.get_mut().0 |
170 | | } |
171 | | pub fn into_inner(self) -> R { |
172 | | self.0.into_inner() |
173 | | } |
174 | | } |
175 | | |
176 | | |
177 | | #[cfg(feature="std")] |
178 | | impl<R: Read> Read for Decompressor<R> { |
179 | 0 | fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> { |
180 | 0 | self.0.read(buf) |
181 | 0 | } Unexecuted instantiation: <brotli_decompressor::reader::Decompressor<&[u8]> as std::io::Read>::read Unexecuted instantiation: <brotli_decompressor::reader::Decompressor<_> as std::io::Read>::read |
182 | | } |
183 | | |
184 | | pub struct DecompressorCustomIo<ErrType, |
185 | | R: CustomRead<ErrType>, |
186 | | BufferType: SliceWrapperMut<u8>, |
187 | | AllocU8: Allocator<u8>, |
188 | | AllocU32: Allocator<u32>, |
189 | | AllocHC: Allocator<HuffmanCode>> |
190 | | { |
191 | | input_buffer: BufferType, |
192 | | total_out: usize, |
193 | | input_offset: usize, |
194 | | input_len: usize, |
195 | | input: R, |
196 | | error_if_invalid_data: Option<ErrType>, |
197 | | state: BrotliState<AllocU8, AllocU32, AllocHC>, |
198 | | done: bool, |
199 | | } |
200 | | |
201 | | impl<ErrType, |
202 | | R: CustomRead<ErrType>, |
203 | | BufferType : SliceWrapperMut<u8>, |
204 | | AllocU8, |
205 | | AllocU32, |
206 | | AllocHC> DecompressorCustomIo<ErrType, R, BufferType, AllocU8, AllocU32, AllocHC> |
207 | | where AllocU8 : Allocator<u8>, AllocU32 : Allocator<u32>, AllocHC : Allocator<HuffmanCode> |
208 | | { |
209 | | |
210 | 0 | pub fn new(r: R, buffer : BufferType, |
211 | 0 | alloc_u8 : AllocU8, alloc_u32 : AllocU32, alloc_hc : AllocHC, |
212 | 0 | invalid_data_error_type : ErrType) -> Self { |
213 | 0 | let dict = AllocU8::AllocatedMemory::default(); |
214 | 0 | Self::new_with_custom_dictionary(r, buffer, alloc_u8, alloc_u32, alloc_hc, dict, invalid_data_error_type) |
215 | 0 | } |
216 | 0 | pub fn new_with_custom_dictionary(r: R, buffer : BufferType, |
217 | 0 | alloc_u8 : AllocU8, alloc_u32 : AllocU32, alloc_hc : AllocHC, |
218 | 0 | dict: AllocU8::AllocatedMemory, |
219 | 0 | invalid_data_error_type : ErrType) -> Self { |
220 | 0 | DecompressorCustomIo::<ErrType, R, BufferType, AllocU8, AllocU32, AllocHC>{ |
221 | 0 | input_buffer : buffer, |
222 | 0 | total_out : 0, |
223 | 0 | input_offset : 0, |
224 | 0 | input_len : 0, |
225 | 0 | input: r, |
226 | 0 | state : BrotliState::new_with_custom_dictionary(alloc_u8, |
227 | 0 | alloc_u32, |
228 | 0 | alloc_hc, |
229 | 0 | dict), |
230 | 0 | error_if_invalid_data : Some(invalid_data_error_type), |
231 | 0 | done: false, |
232 | 0 | } |
233 | 0 | } Unexecuted instantiation: <brotli_decompressor::reader::DecompressorCustomIo<std::io::error::Error, brotli_decompressor::io_wrappers::IntoIoReader<&[u8]>, alloc_stdlib::heap_alloc::WrapBox<u8>, alloc_stdlib::std_alloc::StandardAlloc, alloc_stdlib::std_alloc::StandardAlloc, alloc_stdlib::std_alloc::StandardAlloc>>::new_with_custom_dictionary Unexecuted instantiation: <brotli_decompressor::reader::DecompressorCustomIo<_, _, _, _, _, _>>::new_with_custom_dictionary |
234 | | |
235 | 0 | pub fn get_ref(&self) -> &R { |
236 | 0 | &self.input |
237 | 0 | } |
238 | 0 | pub fn get_mut(&mut self) -> &mut R { |
239 | 0 | &mut self.input |
240 | 0 | } |
241 | 0 | pub fn into_inner(self) -> R { |
242 | 0 | match self { |
243 | | DecompressorCustomIo { |
244 | 0 | input_buffer: _ib, |
245 | 0 | total_out: _to, |
246 | 0 | state: _state, |
247 | 0 | input_offset: _io, |
248 | 0 | input_len: _il, |
249 | 0 | error_if_invalid_data:_eiid, |
250 | 0 | input, |
251 | 0 | done: _done, |
252 | | } =>{ |
253 | 0 | input |
254 | | } |
255 | | } |
256 | 0 | } |
257 | | |
258 | 0 | pub fn copy_to_front(&mut self) { |
259 | 0 | let avail_in = self.input_len - self.input_offset; |
260 | 0 | if self.input_offset == self.input_buffer.slice_mut().len() { |
261 | 0 | self.input_offset = 0; |
262 | 0 | self.input_len = 0; |
263 | 0 | } else if self.input_offset + 256 > self.input_buffer.slice_mut().len() && avail_in < self.input_offset { |
264 | 0 | let (first, second) = self.input_buffer.slice_mut().split_at_mut(self.input_offset); |
265 | 0 | self.input_len -= self.input_offset; |
266 | 0 | first[0..avail_in].clone_from_slice(&second[0..avail_in]); |
267 | 0 | self.input_offset = 0; |
268 | 0 | } |
269 | 0 | } Unexecuted instantiation: <brotli_decompressor::reader::DecompressorCustomIo<std::io::error::Error, brotli_decompressor::io_wrappers::IntoIoReader<&[u8]>, alloc_stdlib::heap_alloc::WrapBox<u8>, alloc_stdlib::std_alloc::StandardAlloc, alloc_stdlib::std_alloc::StandardAlloc, alloc_stdlib::std_alloc::StandardAlloc>>::copy_to_front Unexecuted instantiation: <brotli_decompressor::reader::DecompressorCustomIo<_, _, _, _, _, _>>::copy_to_front |
270 | | } |
271 | | |
272 | | impl<ErrType, |
273 | | R: CustomRead<ErrType>, |
274 | | BufferType : SliceWrapperMut<u8>, |
275 | | AllocU8 : Allocator<u8>, |
276 | | AllocU32 : Allocator<u32>, |
277 | | AllocHC : Allocator<HuffmanCode> > CustomRead<ErrType> for DecompressorCustomIo<ErrType, |
278 | | R, |
279 | | BufferType, |
280 | | AllocU8, |
281 | | AllocU32, |
282 | | AllocHC> { |
283 | | /// This variant of read will return Ok(number of bytes read) until the file |
284 | | /// Is completed at which point it will return Ok(0). |
285 | | /// However if there are additional unconsumed bytes in the buffer, it will |
286 | | /// return Err(InvalidData) at that point. Otherwise it will keep returning |
287 | | /// Ok(0). |
288 | | /// |
289 | | /// # Arguments |
290 | | /// |
291 | | /// * `buf` - The buffer to read into |
292 | | /// |
293 | | /// # Errors |
294 | | /// |
295 | | /// Returns Ok(0) if the file has been fully decompressed. |
296 | | /// If the file has been fully decompressed but there are additional |
297 | | /// non-brotli bytes in the buffer, then return an InvalidData error. |
298 | | /// Also upstream errors from the reader are returned. |
299 | 0 | fn read(&mut self, buf: &mut [u8]) -> Result<usize, ErrType > { |
300 | 0 | let mut output_offset : usize = 0; |
301 | 0 | let mut avail_out = buf.len() - output_offset; |
302 | 0 | let mut avail_in = self.input_len - self.input_offset; |
303 | 0 | while avail_out == buf.len() { |
304 | 0 | match BrotliDecompressStream(&mut avail_in, |
305 | 0 | &mut self.input_offset, |
306 | 0 | &self.input_buffer.slice_mut()[..], |
307 | 0 | &mut avail_out, |
308 | 0 | &mut output_offset, |
309 | 0 | buf, |
310 | 0 | &mut self.total_out, |
311 | 0 | &mut self.state) { |
312 | | BrotliResult::NeedsMoreInput => { |
313 | 0 | self.copy_to_front(); |
314 | 0 | if output_offset != 0 { |
315 | | // The decompressor successfully decoded some bytes, but still requires more |
316 | | // we do not wish to risk self.input.read returning an error, so instead we |
317 | | // opt to return what we have and do not invoke the read trait method |
318 | 0 | return Ok(output_offset); |
319 | 0 | } |
320 | 0 | match self.input.read(&mut self.input_buffer.slice_mut()[self.input_len..]) { |
321 | 0 | Err(e) => { |
322 | 0 | return Err(e); |
323 | | }, |
324 | 0 | Ok(size) => if size == 0 { |
325 | 0 | return self.error_if_invalid_data.take().map(|e| Err(e)).unwrap_or(Ok(0)); Unexecuted instantiation: <brotli_decompressor::reader::DecompressorCustomIo<std::io::error::Error, brotli_decompressor::io_wrappers::IntoIoReader<&[u8]>, alloc_stdlib::heap_alloc::WrapBox<u8>, alloc_stdlib::std_alloc::StandardAlloc, alloc_stdlib::std_alloc::StandardAlloc, alloc_stdlib::std_alloc::StandardAlloc> as brotli_decompressor::io_wrappers::CustomRead<std::io::error::Error>>::read::{closure#0} Unexecuted instantiation: <brotli_decompressor::reader::DecompressorCustomIo<_, _, _, _, _, _> as brotli_decompressor::io_wrappers::CustomRead<_>>::read::{closure#0} |
326 | 0 | }else { |
327 | 0 | self.input_len += size; |
328 | 0 | avail_in = self.input_len - self.input_offset; |
329 | 0 | }, |
330 | | } |
331 | | }, |
332 | | BrotliResult::NeedsMoreOutput => { |
333 | 0 | break; |
334 | | }, |
335 | | BrotliResult::ResultSuccess => { |
336 | 0 | if output_offset == 0 { |
337 | 0 | if !self.done { |
338 | 0 | self.done = true; |
339 | 0 | } else if self.input_len != self.input_offset { |
340 | | // Did not consume entire input; report error. |
341 | 0 | return self.error_if_invalid_data.take().map(|e| Err(e)).unwrap_or(Ok(output_offset)); Unexecuted instantiation: <brotli_decompressor::reader::DecompressorCustomIo<std::io::error::Error, brotli_decompressor::io_wrappers::IntoIoReader<&[u8]>, alloc_stdlib::heap_alloc::WrapBox<u8>, alloc_stdlib::std_alloc::StandardAlloc, alloc_stdlib::std_alloc::StandardAlloc, alloc_stdlib::std_alloc::StandardAlloc> as brotli_decompressor::io_wrappers::CustomRead<std::io::error::Error>>::read::{closure#1} Unexecuted instantiation: <brotli_decompressor::reader::DecompressorCustomIo<_, _, _, _, _, _> as brotli_decompressor::io_wrappers::CustomRead<_>>::read::{closure#1} |
342 | 0 | } |
343 | 0 | } |
344 | 0 | return Ok(output_offset); |
345 | | } |
346 | 0 | BrotliResult::ResultFailure => return self.error_if_invalid_data.take().map(|e| Err(e)).unwrap_or(Ok(0)), Unexecuted instantiation: <brotli_decompressor::reader::DecompressorCustomIo<std::io::error::Error, brotli_decompressor::io_wrappers::IntoIoReader<&[u8]>, alloc_stdlib::heap_alloc::WrapBox<u8>, alloc_stdlib::std_alloc::StandardAlloc, alloc_stdlib::std_alloc::StandardAlloc, alloc_stdlib::std_alloc::StandardAlloc> as brotli_decompressor::io_wrappers::CustomRead<std::io::error::Error>>::read::{closure#2} Unexecuted instantiation: <brotli_decompressor::reader::DecompressorCustomIo<_, _, _, _, _, _> as brotli_decompressor::io_wrappers::CustomRead<_>>::read::{closure#2} |
347 | | } |
348 | | } |
349 | 0 | Ok(output_offset) |
350 | 0 | } Unexecuted instantiation: <brotli_decompressor::reader::DecompressorCustomIo<std::io::error::Error, brotli_decompressor::io_wrappers::IntoIoReader<&[u8]>, alloc_stdlib::heap_alloc::WrapBox<u8>, alloc_stdlib::std_alloc::StandardAlloc, alloc_stdlib::std_alloc::StandardAlloc, alloc_stdlib::std_alloc::StandardAlloc> as brotli_decompressor::io_wrappers::CustomRead<std::io::error::Error>>::read Unexecuted instantiation: <brotli_decompressor::reader::DecompressorCustomIo<_, _, _, _, _, _> as brotli_decompressor::io_wrappers::CustomRead<_>>::read |
351 | | } |
352 | | |
353 | | #[cfg(feature="std")] |
354 | | #[test] |
355 | | fn test_no_vanishing_bytes() { |
356 | | use std::string::ToString; |
357 | | |
358 | | // Output from this command: |
359 | | let compressed_with_extra = b"\x8f\x02\x80\x68\x65\x6c\x6c\x6f\x0a\x03\x67\x6f\x6f\x64\x62\x79\x65\x0a"; |
360 | | // Make sure that read_to_string returns the data. |
361 | | let cursor = std::io::Cursor::new(compressed_with_extra); |
362 | | let mut reader = super::Decompressor::new(cursor, 8000); |
363 | | assert_eq!(std::io::read_to_string(&mut reader).unwrap(), "hello\n"); |
364 | | |
365 | | // However you can call read extra times to make sure there's no data. |
366 | | let cursor = std::io::Cursor::new(compressed_with_extra); |
367 | | let mut reader = super::Decompressor::new(cursor, 8000); |
368 | | let mut data = std::vec::Vec::<u8>::default(); |
369 | | loop { |
370 | | let mut buf = [0u8;5]; |
371 | | let offset = reader.read(&mut buf).unwrap(); |
372 | | if offset == 0 { |
373 | | break; |
374 | | } |
375 | | data.extend_from_slice(&buf[..offset]); |
376 | | } |
377 | | assert_eq!( |
378 | | &data, |
379 | | &['h' as u8, 'e' as u8, 'l' as u8, 'l' as u8, 'o' as u8, '\n' as u8]); |
380 | | |
381 | | // But calling read, one last time, results in an error because there |
382 | | // were leftover bytes in the buffer. |
383 | | let mut buf = [0u8;5]; |
384 | | assert_eq!(reader.read(&mut buf).unwrap_err().kind(), |
385 | | io::ErrorKind::InvalidData); |
386 | | data.clear(); |
387 | | |
388 | | |
389 | | } |
390 | | |
391 | | #[cfg(feature="std")] |
392 | | #[test] |
393 | | fn test_repeated_read_returns_zero() { |
394 | | use std::string::ToString; |
395 | | |
396 | | // Output from this command: |
397 | | let compressed_without_extra = b"\x8f\x02\x80\x68\x65\x6c\x6c\x6f\x0a\x03"; |
398 | | // Make sure that read_to_string returns the data. |
399 | | let cursor = std::io::Cursor::new(compressed_without_extra); |
400 | | let mut reader = super::Decompressor::new(cursor, 8000); |
401 | | assert_eq!(std::io::read_to_string(&mut reader).unwrap(), "hello\n"); |
402 | | |
403 | | // However you can call read extra times to make sure there's no data. |
404 | | let cursor = std::io::Cursor::new(compressed_without_extra); |
405 | | let mut reader = super::Decompressor::new(cursor, 8000); |
406 | | let mut data = std::vec::Vec::<u8>::default(); |
407 | | loop { |
408 | | let mut buf = [0u8;5]; |
409 | | let offset = reader.read(&mut buf).unwrap(); |
410 | | if offset == 0 { |
411 | | break; |
412 | | } |
413 | | data.extend_from_slice(&buf[..offset]); |
414 | | } |
415 | | assert_eq!(&data, &['h' as u8, 'e' as u8, 'l' as u8, 'l' as u8, 'o' as u8, '\n' as u8]); |
416 | | let mut buf = [0u8;5]; |
417 | | assert_eq!(reader.read(&mut buf).unwrap(), 0); |
418 | | data.clear(); |
419 | | |
420 | | |
421 | | } |
422 | | |