MCPcopy Create free account
hub / github.com/apache/avro-rs / decompress

Method decompress

avro/src/codec.rs:146–222  ·  view source on GitHub ↗

Decompress a stream of bytes in-place.

(self, stream: &mut Vec<u8>)

Source from the content-addressed store, hash-verified

144 /// Decompress a stream of bytes in-place.
145 pub fn decompress(self, stream: &mut Vec<u8>) -> AvroResult<()> {
146 // Cap the decompressed output at the configured allocation budget so a
147 // small compressed block cannot inflate to an enormous buffer (a
148 // "decompression bomb") and exhaust memory.
149 let max_bytes =
150 crate::util::max_allocation_bytes(crate::util::DEFAULT_MAX_ALLOCATION_BYTES);
151 *stream = match self {
152 Codec::Null => return Ok(()),
153 Codec::Deflate(_settings) => miniz_oxide::inflate::decompress_to_vec_with_limit(stream, max_bytes).map_err(|e| {
154 use std::io::ErrorKind;
155 use miniz_oxide::inflate::TINFLStatus;
156
157 let details = match e.status {
158 TINFLStatus::FailedCannotMakeProgress | TINFLStatus::NeedsMoreInput => Details::DeflateDecompress(ErrorKind::UnexpectedEof.into()),
159 TINFLStatus::Adler32Mismatch | TINFLStatus::Failed | TINFLStatus::BadParam => Details::DeflateDecompress(ErrorKind::InvalidData.into()),
160 TINFLStatus::Done => Details::DeflateDecompress(std::io::Error::other("Unexpected error: miniz_oxide reported an error with a success status. Please report this to avro-rs developers.")),
161 // Output is larger than max allocation allowed
162 TINFLStatus::HasMoreOutput => Details::MemoryAllocation {
163 desired: None,
164 maximum: max_bytes,
165 },
166 other => Details::DeflateDecompress(std::io::Error::other(format!("Unexpected error: {other:?}")))
167 };
168 Error::new(details)
169 })?,
170 #[cfg(feature = "snappy")]
171 Codec::Snappy => {
172 // The block ends with a 4-byte CRC32; a truncated/corrupt block
173 // shorter than that must error rather than underflow the slice.
174 let data_end = stream
175 .len()
176 .checked_sub(4)
177 .ok_or(Details::BadSnappyLength(stream.len()))?;
178 let decompressed_size = snap::raw::decompress_len(&stream[..data_end])
179 .map_err(Details::GetSnappyDecompressLen)?;
180 // The decompressed size is taken from the (untrusted) block
181 // header, so bound it before allocating for it.
182 let decompressed_size = crate::util::safe_len(decompressed_size)?;
183 let mut decoded = vec![0; decompressed_size];
184 snap::raw::Decoder::new()
185 .decompress(&stream[..data_end], &mut decoded[..])
186 .map_err(Details::SnappyDecompress)?;
187
188 let mut last_four: [u8; 4] = [0; 4];
189 last_four.copy_from_slice(&stream[data_end..]);
190 let expected: u32 = u32::from_be_bytes(last_four);
191
192 let actual = crc_fast::crc32_iso_hdlc(&decoded);
193
194 if expected != actual {
195 return Err(Details::SnappyCrc32{expected, actual}.into());
196 }
197 decoded
198 }
199 #[cfg(feature = "zstandard")]
200 Codec::Zstandard(_settings) => {
201 use std::io::{BufReader, Read};
202 use zstd::zstd_safe;
203

Callers 3

compress_and_decompressFunction · 0.80
read_block_nextMethod · 0.80

Calls 2

updateMethod · 0.80
lenMethod · 0.45

Tested by 1