1
- pub use flate2:: { Decompress , Status } ;
1
+ use std:: ffi:: c_int;
2
+
3
+ /// A type to hold all state needed for decompressing a ZLIB encoded stream.
4
+ pub struct Decompress ( libz_rs_sys:: z_stream ) ;
5
+
6
+ unsafe impl Sync for Decompress { }
7
+ unsafe impl Send for Decompress { }
8
+
9
+ impl Default for Decompress {
10
+ fn default ( ) -> Self {
11
+ Self :: new ( )
12
+ }
13
+ }
14
+
15
+ impl Decompress {
16
+ /// The amount of bytes consumed from the input so far.
17
+ pub fn total_in ( & self ) -> u64 {
18
+ self . 0 . total_in as _
19
+ }
20
+
21
+ /// The amount of decompressed bytes that have been written to the output thus far.
22
+ pub fn total_out ( & self ) -> u64 {
23
+ self . 0 . total_out as _
24
+ }
25
+
26
+ /// Create a new instance. Note that it allocates in various ways and thus should be re-used.
27
+ pub fn new ( ) -> Self {
28
+ let mut this = libz_rs_sys:: z_stream:: default ( ) ;
29
+
30
+ unsafe {
31
+ libz_rs_sys:: inflateInit_ (
32
+ & mut this,
33
+ libz_rs_sys:: zlibVersion ( ) ,
34
+ core:: mem:: size_of :: < libz_rs_sys:: z_stream > ( ) as core:: ffi:: c_int ,
35
+ ) ;
36
+ }
37
+
38
+ Self ( this)
39
+ }
40
+
41
+ /// Reset the state to allow handling a new stream.
42
+ pub fn reset ( & mut self ) {
43
+ unsafe { libz_rs_sys:: inflateReset ( & mut self . 0 ) } ;
44
+ }
45
+
46
+ /// Decompress `input` and write all decompressed bytes into `output`, with `flush` defining some details about this.
47
+ pub fn decompress (
48
+ & mut self ,
49
+ input : & [ u8 ] ,
50
+ output : & mut [ u8 ] ,
51
+ flush : FlushDecompress ,
52
+ ) -> Result < Status , DecompressError > {
53
+ self . 0 . avail_in = input. len ( ) as _ ;
54
+ self . 0 . avail_out = output. len ( ) as _ ;
55
+
56
+ self . 0 . next_in = input. as_ptr ( ) ;
57
+ self . 0 . next_out = output. as_mut_ptr ( ) ;
58
+
59
+ match unsafe { libz_rs_sys:: inflate ( & mut self . 0 , flush as _ ) } {
60
+ libz_rs_sys:: Z_OK => Ok ( Status :: Ok ) ,
61
+ libz_rs_sys:: Z_BUF_ERROR => Ok ( Status :: BufError ) ,
62
+ libz_rs_sys:: Z_STREAM_END => Ok ( Status :: StreamEnd ) ,
63
+
64
+ libz_rs_sys:: Z_STREAM_ERROR => Err ( DecompressError :: StreamError ) ,
65
+ libz_rs_sys:: Z_DATA_ERROR => Err ( DecompressError :: DataError ) ,
66
+ libz_rs_sys:: Z_MEM_ERROR => Err ( DecompressError :: InsufficientMemory ) ,
67
+ err => Err ( DecompressError :: Unknown { err } ) ,
68
+ }
69
+ }
70
+ }
71
+
72
+ impl Drop for Decompress {
73
+ fn drop ( & mut self ) {
74
+ unsafe { libz_rs_sys:: inflateEnd ( & mut self . 0 ) } ;
75
+ }
76
+ }
77
+
78
+ /// The error produced by [`Decompress::decompress()`].
79
+ #[ derive( Debug , thiserror:: Error ) ]
80
+ #[ allow( missing_docs) ]
81
+ pub enum DecompressError {
82
+ #[ error( "stream error" ) ]
83
+ StreamError ,
84
+ #[ error( "Not enough memory" ) ]
85
+ InsufficientMemory ,
86
+ #[ error( "Invalid input data" ) ]
87
+ DataError ,
88
+ #[ error( "An unknown error occurred: {err}" ) ]
89
+ Unknown { err : c_int } ,
90
+ }
91
+
92
+ /// The status returned by [`Decompress::decompress()`].
93
+ #[ derive( Debug , Clone , Copy , PartialEq , Eq ) ]
94
+ pub enum Status {
95
+ /// The decompress operation went well. Not to be confused with `StreamEnd`, so one can continue
96
+ /// the decompression.
97
+ Ok ,
98
+ /// An error occurred when decompression.
99
+ BufError ,
100
+ /// The stream was fully decompressed.
101
+ StreamEnd ,
102
+ }
103
+
104
+ /// Values which indicate the form of flushing to be used when
105
+ /// decompressing in-memory data.
106
+ #[ derive( Copy , Clone , PartialEq , Eq , Debug ) ]
107
+ #[ non_exhaustive]
108
+ #[ allow( clippy:: unnecessary_cast) ]
109
+ pub enum FlushDecompress {
110
+ /// A typical parameter for passing to compression/decompression functions,
111
+ /// this indicates that the underlying stream to decide how much data to
112
+ /// accumulate before producing output in order to maximize compression.
113
+ None = libz_rs_sys:: Z_NO_FLUSH as isize ,
114
+
115
+ /// All pending output is flushed to the output buffer and the output is
116
+ /// aligned on a byte boundary so that the decompressor can get all input
117
+ /// data available so far.
118
+ ///
119
+ /// Flushing may degrade compression for some compression algorithms and so
120
+ /// it should only be used when necessary. This will complete the current
121
+ /// deflate block and follow it with an empty stored block.
122
+ Sync = libz_rs_sys:: Z_SYNC_FLUSH as isize ,
123
+
124
+ /// Pending input is processed and pending output is flushed.
125
+ ///
126
+ /// The return value may indicate that the stream is not yet done and more
127
+ /// data has yet to be processed.
128
+ Finish = libz_rs_sys:: Z_FINISH as isize ,
129
+ }
2
130
3
131
/// non-streaming interfaces for decompression
4
132
pub mod inflate {
@@ -8,33 +136,26 @@ pub mod inflate {
8
136
pub enum Error {
9
137
#[ error( "Could not write all bytes when decompressing content" ) ]
10
138
WriteInflated ( #[ from] std:: io:: Error ) ,
11
- #[ error( "Could not decode zip stream, status was '{0:? }'" ) ]
12
- Inflate ( #[ from] flate2 :: DecompressError ) ,
139
+ #[ error( "Could not decode zip stream, status was '{0}'" ) ]
140
+ Inflate ( #[ from] super :: DecompressError ) ,
13
141
#[ error( "The zlib status indicated an error, status was '{0:?}'" ) ]
14
- Status ( flate2 :: Status ) ,
142
+ Status ( super :: Status ) ,
15
143
}
16
144
}
17
145
18
146
/// Decompress a few bytes of a zlib stream without allocation
147
+ #[ derive( Default ) ]
19
148
pub struct Inflate {
20
149
/// The actual decompressor doing all the work.
21
150
pub state : Decompress ,
22
151
}
23
152
24
- impl Default for Inflate {
25
- fn default ( ) -> Self {
26
- Inflate {
27
- state : Decompress :: new ( true ) ,
28
- }
29
- }
30
- }
31
-
32
153
impl Inflate {
33
154
/// Run the decompressor exactly once. Cannot be run multiple times
34
- pub fn once ( & mut self , input : & [ u8 ] , out : & mut [ u8 ] ) -> Result < ( flate2 :: Status , usize , usize ) , inflate:: Error > {
155
+ pub fn once ( & mut self , input : & [ u8 ] , out : & mut [ u8 ] ) -> Result < ( Status , usize , usize ) , inflate:: Error > {
35
156
let before_in = self . state . total_in ( ) ;
36
157
let before_out = self . state . total_out ( ) ;
37
- let status = self . state . decompress ( input, out, flate2 :: FlushDecompress :: None ) ?;
158
+ let status = self . state . decompress ( input, out, FlushDecompress :: None ) ?;
38
159
Ok ( (
39
160
status,
40
161
( self . state . total_in ( ) - before_in) as usize ,
@@ -44,7 +165,7 @@ impl Inflate {
44
165
45
166
/// Ready this instance for decoding another data stream.
46
167
pub fn reset ( & mut self ) {
47
- self . state . reset ( true ) ;
168
+ self . state . reset ( ) ;
48
169
}
49
170
}
50
171
0 commit comments