/rust/registry/src/index.crates.io-1949cf8c6b5b557f/bzip2-0.4.4/src/mem.rs
Line | Count | Source |
1 | | //! Raw low-level manipulations of bz streams. |
2 | | |
3 | | use std::error; |
4 | | use std::fmt; |
5 | | use std::marker; |
6 | | use std::mem; |
7 | | use std::slice; |
8 | | |
9 | | use libc::{c_int, c_uint}; |
10 | | |
11 | | use {ffi, Compression}; |
12 | | |
13 | | /// Representation of an in-memory compression stream. |
14 | | /// |
15 | | /// An instance of `Compress` can be used to compress a stream of bz2 data. |
16 | | pub struct Compress { |
17 | | inner: Stream<DirCompress>, |
18 | | } |
19 | | |
20 | | /// Representation of an in-memory decompression stream. |
21 | | /// |
22 | | /// An instance of `Decompress` can be used to inflate a stream of bz2-encoded |
23 | | /// data. |
24 | | pub struct Decompress { |
25 | | inner: Stream<DirDecompress>, |
26 | | } |
27 | | |
28 | | struct Stream<D: Direction> { |
29 | | // libbz2 requires a stable address for this stream. |
30 | | raw: Box<ffi::bz_stream>, |
31 | | _marker: marker::PhantomData<D>, |
32 | | } |
33 | | |
34 | | unsafe impl<D: Direction> Send for Stream<D> {} |
35 | | unsafe impl<D: Direction> Sync for Stream<D> {} |
36 | | |
37 | | trait Direction { |
38 | | unsafe fn destroy(stream: *mut ffi::bz_stream) -> c_int; |
39 | | } |
40 | | |
41 | | enum DirCompress {} |
42 | | enum DirDecompress {} |
43 | | |
44 | | /// Possible actions to take on compression. |
45 | | #[derive(PartialEq, Eq, Copy, Debug, Clone)] |
46 | | pub enum Action { |
47 | | /// Normal compression. |
48 | | Run = ffi::BZ_RUN as isize, |
49 | | /// Request that the current compression block is terminate. |
50 | | Flush = ffi::BZ_FLUSH as isize, |
51 | | /// Request that the compression stream be finalized. |
52 | | Finish = ffi::BZ_FINISH as isize, |
53 | | } |
54 | | |
55 | | /// Result of compression or decompression |
56 | | #[derive(PartialEq, Eq, Copy, Debug, Clone)] |
57 | | pub enum Status { |
58 | | /// Decompression went fine, nothing much to report. |
59 | | Ok, |
60 | | |
61 | | /// The Flush action on a compression went ok. |
62 | | FlushOk, |
63 | | |
64 | | /// THe Run action on compression went ok. |
65 | | RunOk, |
66 | | |
67 | | /// The Finish action on compression went ok. |
68 | | FinishOk, |
69 | | |
70 | | /// The stream's end has been met, meaning that no more data can be input. |
71 | | StreamEnd, |
72 | | |
73 | | /// There was insufficient memory in the input or output buffer to complete |
74 | | /// the request, but otherwise everything went normally. |
75 | | MemNeeded, |
76 | | } |
77 | | |
78 | | /// Fatal errors encountered when compressing/decompressing bytes. |
79 | | /// |
80 | | /// These errors indicate that progress could not be made in any form due to |
81 | | /// input or output parameters. |
82 | | #[derive(PartialEq, Eq, Copy, Debug, Clone)] |
83 | | pub enum Error { |
84 | | /// The sequence of operations called on a decompression/compression stream |
85 | | /// were invalid. See methods for details. |
86 | | Sequence, |
87 | | |
88 | | /// The data being decompressed was invalid, or it was not a valid bz2 |
89 | | /// stream. |
90 | | Data, |
91 | | |
92 | | /// The magic bz2 header wasn't present when decompressing. |
93 | | DataMagic, |
94 | | |
95 | | /// The parameters to this function were invalid. |
96 | | Param, |
97 | | } |
98 | | |
99 | | impl Compress { |
100 | | /// Creates a new stream prepared for compression. |
101 | | /// |
102 | | /// The `work_factor` parameter controls how the compression phase behaves |
103 | | /// when presented with worst case, highly repetitive, input data. If |
104 | | /// compression runs into difficulties caused by repetitive data, the |
105 | | /// library switches from the standard sorting algorithm to a fallback |
106 | | /// algorithm. The fallback is slower than the standard algorithm by perhaps |
107 | | /// a factor of three, but always behaves reasonably, no matter how bad the |
108 | | /// input. |
109 | | /// |
110 | | /// Lower values of `work_factor` reduce the amount of effort the standard |
111 | | /// algorithm will expend before resorting to the fallback. You should set |
112 | | /// this parameter carefully; too low, and many inputs will be handled by |
113 | | /// the fallback algorithm and so compress rather slowly, too high, and your |
114 | | /// average-to-worst case compression times can become very large. The |
115 | | /// default value of 30 gives reasonable behaviour over a wide range of |
116 | | /// circumstances. |
117 | | /// |
118 | | /// Allowable values range from 0 to 250 inclusive. 0 is a special case, |
119 | | /// equivalent to using the default value of 30. |
120 | 3.59k | pub fn new(lvl: Compression, work_factor: u32) -> Compress { |
121 | | unsafe { |
122 | 3.59k | let mut raw = Box::new(mem::zeroed()); |
123 | 3.59k | assert_eq!( |
124 | 3.59k | ffi::BZ2_bzCompressInit(&mut *raw, lvl.level() as c_int, 0, work_factor as c_int), |
125 | | 0 |
126 | | ); |
127 | 3.59k | Compress { |
128 | 3.59k | inner: Stream { |
129 | 3.59k | raw: raw, |
130 | 3.59k | _marker: marker::PhantomData, |
131 | 3.59k | }, |
132 | 3.59k | } |
133 | | } |
134 | 3.59k | } |
135 | | |
136 | | /// Compress a block of input into a block of output. |
137 | | /// |
138 | | /// If anything other than BZ_OK is seen, `Err` is returned. The action |
139 | | /// given must be one of Run, Flush or Finish. |
140 | 7.19k | pub fn compress( |
141 | 7.19k | &mut self, |
142 | 7.19k | input: &[u8], |
143 | 7.19k | output: &mut [u8], |
144 | 7.19k | action: Action, |
145 | 7.19k | ) -> Result<Status, Error> { |
146 | | // apparently 0-length compression requests which don't actually make |
147 | | // any progress are returned as BZ_PARAM_ERROR, which we don't want, to |
148 | | // just translate to a success here. |
149 | 7.19k | if input.len() == 0 && action == Action::Run { |
150 | 0 | return Ok(Status::RunOk); |
151 | 7.19k | } |
152 | 7.19k | self.inner.raw.next_in = input.as_ptr() as *mut _; |
153 | 7.19k | self.inner.raw.avail_in = input.len().min(c_uint::MAX as usize) as c_uint; |
154 | 7.19k | self.inner.raw.next_out = output.as_mut_ptr() as *mut _; |
155 | 7.19k | self.inner.raw.avail_out = output.len().min(c_uint::MAX as usize) as c_uint; |
156 | | unsafe { |
157 | 7.19k | match ffi::BZ2_bzCompress(&mut *self.inner.raw, action as c_int) { |
158 | 3.59k | ffi::BZ_RUN_OK => Ok(Status::RunOk), |
159 | 0 | ffi::BZ_FLUSH_OK => Ok(Status::FlushOk), |
160 | 0 | ffi::BZ_FINISH_OK => Ok(Status::FinishOk), |
161 | 3.59k | ffi::BZ_STREAM_END => Ok(Status::StreamEnd), |
162 | 0 | ffi::BZ_SEQUENCE_ERROR => Err(Error::Sequence), |
163 | 0 | c => panic!("unknown return status: {}", c), |
164 | | } |
165 | | } |
166 | 7.19k | } |
167 | | |
168 | | /// Compress a block of input into an output vector. |
169 | | /// |
170 | | /// This function will not grow `output`, but it will fill the space after |
171 | | /// its current length up to its capacity. The length of the vector will be |
172 | | /// adjusted appropriately. |
173 | 7.19k | pub fn compress_vec( |
174 | 7.19k | &mut self, |
175 | 7.19k | input: &[u8], |
176 | 7.19k | output: &mut Vec<u8>, |
177 | 7.19k | action: Action, |
178 | 7.19k | ) -> Result<Status, Error> { |
179 | 7.19k | let cap = output.capacity(); |
180 | 7.19k | let len = output.len(); |
181 | | |
182 | | unsafe { |
183 | 7.19k | let before = self.total_out(); |
184 | 7.19k | let ret = { |
185 | 7.19k | let ptr = output.as_mut_ptr().offset(len as isize); |
186 | 7.19k | let out = slice::from_raw_parts_mut(ptr, cap - len); |
187 | 7.19k | self.compress(input, out, action) |
188 | | }; |
189 | 7.19k | output.set_len((self.total_out() - before) as usize + len); |
190 | 7.19k | return ret; |
191 | | } |
192 | 7.19k | } |
193 | | |
194 | | /// Total number of bytes processed as input |
195 | 7.19k | pub fn total_in(&self) -> u64 { |
196 | 7.19k | self.inner.total_in() |
197 | 7.19k | } |
198 | | |
199 | | /// Total number of bytes processed as output |
200 | 14.3k | pub fn total_out(&self) -> u64 { |
201 | 14.3k | self.inner.total_out() |
202 | 14.3k | } |
203 | | } |
204 | | |
205 | | impl Decompress { |
206 | | /// Creates a new stream prepared for decompression. |
207 | | /// |
208 | | /// If `small` is true, then the library will use an alternative |
209 | | /// decompression algorithm which uses less memory but at the cost of |
210 | | /// decompressing more slowly (roughly speaking, half the speed, but the |
211 | | /// maximum memory requirement drops to around 2300k). See |
212 | 1.67k | pub fn new(small: bool) -> Decompress { |
213 | | unsafe { |
214 | 1.67k | let mut raw = Box::new(mem::zeroed()); |
215 | 1.67k | assert_eq!(ffi::BZ2_bzDecompressInit(&mut *raw, 0, small as c_int), 0); |
216 | 1.67k | Decompress { |
217 | 1.67k | inner: Stream { |
218 | 1.67k | raw: raw, |
219 | 1.67k | _marker: marker::PhantomData, |
220 | 1.67k | }, |
221 | 1.67k | } |
222 | | } |
223 | 1.67k | } |
224 | | |
225 | | /// Decompress a block of input into a block of output. |
226 | 2.51k | pub fn decompress(&mut self, input: &[u8], output: &mut [u8]) -> Result<Status, Error> { |
227 | 2.51k | self.inner.raw.next_in = input.as_ptr() as *mut _; |
228 | 2.51k | self.inner.raw.avail_in = input.len().min(c_uint::MAX as usize) as c_uint; |
229 | 2.51k | self.inner.raw.next_out = output.as_mut_ptr() as *mut _; |
230 | 2.51k | self.inner.raw.avail_out = output.len().min(c_uint::MAX as usize) as c_uint; |
231 | | unsafe { |
232 | 2.51k | match ffi::BZ2_bzDecompress(&mut *self.inner.raw) { |
233 | 903 | ffi::BZ_OK => Ok(Status::Ok), |
234 | 0 | ffi::BZ_MEM_ERROR => Ok(Status::MemNeeded), |
235 | 1.03k | ffi::BZ_STREAM_END => Ok(Status::StreamEnd), |
236 | 0 | ffi::BZ_PARAM_ERROR => Err(Error::Param), |
237 | 288 | ffi::BZ_DATA_ERROR => Err(Error::Data), |
238 | 286 | ffi::BZ_DATA_ERROR_MAGIC => Err(Error::DataMagic), |
239 | 0 | ffi::BZ_SEQUENCE_ERROR => Err(Error::Sequence), |
240 | 0 | c => panic!("wut: {}", c), |
241 | | } |
242 | | } |
243 | 2.51k | } |
244 | | |
245 | | /// Decompress a block of input into an output vector. |
246 | | /// |
247 | | /// This function will not grow `output`, but it will fill the space after |
248 | | /// its current length up to its capacity. The length of the vector will be |
249 | | /// adjusted appropriately. |
250 | 0 | pub fn decompress_vec(&mut self, input: &[u8], output: &mut Vec<u8>) -> Result<Status, Error> { |
251 | 0 | let cap = output.capacity(); |
252 | 0 | let len = output.len(); |
253 | | |
254 | | unsafe { |
255 | 0 | let before = self.total_out(); |
256 | 0 | let ret = { |
257 | 0 | let ptr = output.as_mut_ptr().offset(len as isize); |
258 | 0 | let out = slice::from_raw_parts_mut(ptr, cap - len); |
259 | 0 | self.decompress(input, out) |
260 | | }; |
261 | 0 | output.set_len((self.total_out() - before) as usize + len); |
262 | 0 | return ret; |
263 | | } |
264 | 0 | } |
265 | | |
266 | | /// Total number of bytes processed as input |
267 | 5.02k | pub fn total_in(&self) -> u64 { |
268 | 5.02k | self.inner.total_in() |
269 | 5.02k | } |
270 | | |
271 | | /// Total number of bytes processed as output |
272 | 5.02k | pub fn total_out(&self) -> u64 { |
273 | 5.02k | self.inner.total_out() |
274 | 5.02k | } |
275 | | } |
276 | | |
277 | | impl<D: Direction> Stream<D> { |
278 | 12.2k | fn total_in(&self) -> u64 { |
279 | 12.2k | (self.raw.total_in_lo32 as u64) | ((self.raw.total_in_hi32 as u64) << 32) |
280 | 12.2k | } <bzip2::mem::Stream<bzip2::mem::DirCompress>>::total_in Line | Count | Source | 278 | 7.19k | fn total_in(&self) -> u64 { | 279 | 7.19k | (self.raw.total_in_lo32 as u64) | ((self.raw.total_in_hi32 as u64) << 32) | 280 | 7.19k | } |
<bzip2::mem::Stream<bzip2::mem::DirDecompress>>::total_in Line | Count | Source | 278 | 5.02k | fn total_in(&self) -> u64 { | 279 | 5.02k | (self.raw.total_in_lo32 as u64) | ((self.raw.total_in_hi32 as u64) << 32) | 280 | 5.02k | } |
|
281 | | |
282 | 19.4k | fn total_out(&self) -> u64 { |
283 | 19.4k | (self.raw.total_out_lo32 as u64) | ((self.raw.total_out_hi32 as u64) << 32) |
284 | 19.4k | } <bzip2::mem::Stream<bzip2::mem::DirCompress>>::total_out Line | Count | Source | 282 | 14.3k | fn total_out(&self) -> u64 { | 283 | 14.3k | (self.raw.total_out_lo32 as u64) | ((self.raw.total_out_hi32 as u64) << 32) | 284 | 14.3k | } |
<bzip2::mem::Stream<bzip2::mem::DirDecompress>>::total_out Line | Count | Source | 282 | 5.02k | fn total_out(&self) -> u64 { | 283 | 5.02k | (self.raw.total_out_lo32 as u64) | ((self.raw.total_out_hi32 as u64) << 32) | 284 | 5.02k | } |
|
285 | | } |
286 | | |
287 | | impl error::Error for Error {} |
288 | | |
289 | | impl fmt::Display for Error { |
290 | 0 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
291 | 0 | let description = match self { |
292 | 0 | Error::Sequence => "bzip2: sequence of operations invalid", |
293 | 0 | Error::Data => "bzip2: invalid data", |
294 | 0 | Error::DataMagic => "bzip2: bz2 header missing", |
295 | 0 | Error::Param => "bzip2: invalid parameters", |
296 | | }; |
297 | 0 | f.write_str(description) |
298 | 0 | } |
299 | | } |
300 | | |
301 | | impl From<Error> for std::io::Error { |
302 | 0 | fn from(data: Error) -> std::io::Error { |
303 | 0 | std::io::Error::new(std::io::ErrorKind::Other, data) |
304 | 0 | } |
305 | | } |
306 | | |
307 | | impl Direction for DirCompress { |
308 | 3.59k | unsafe fn destroy(stream: *mut ffi::bz_stream) -> c_int { |
309 | 3.59k | ffi::BZ2_bzCompressEnd(stream) |
310 | 3.59k | } |
311 | | } |
312 | | impl Direction for DirDecompress { |
313 | 1.67k | unsafe fn destroy(stream: *mut ffi::bz_stream) -> c_int { |
314 | 1.67k | ffi::BZ2_bzDecompressEnd(stream) |
315 | 1.67k | } |
316 | | } |
317 | | |
318 | | impl<D: Direction> Drop for Stream<D> { |
319 | 5.27k | fn drop(&mut self) { |
320 | 5.27k | unsafe { |
321 | 5.27k | let _ = D::destroy(&mut *self.raw); |
322 | 5.27k | } |
323 | 5.27k | } <bzip2::mem::Stream<bzip2::mem::DirDecompress> as core::ops::drop::Drop>::drop Line | Count | Source | 319 | 1.67k | fn drop(&mut self) { | 320 | 1.67k | unsafe { | 321 | 1.67k | let _ = D::destroy(&mut *self.raw); | 322 | 1.67k | } | 323 | 1.67k | } |
Unexecuted instantiation: <bzip2::mem::Stream<_> as core::ops::drop::Drop>::drop <bzip2::mem::Stream<bzip2::mem::DirCompress> as core::ops::drop::Drop>::drop Line | Count | Source | 319 | 3.59k | fn drop(&mut self) { | 320 | 3.59k | unsafe { | 321 | 3.59k | let _ = D::destroy(&mut *self.raw); | 322 | 3.59k | } | 323 | 3.59k | } |
|
324 | | } |