imago/qcow2/
compressed.rs1use super::*;
4use crate::io_buffers::IoBuffer;
5use miniz_oxide::inflate::core::{decompress as inflate, DecompressorOxide};
6use miniz_oxide::inflate::TINFLStatus;
7
8impl<S: Storage + 'static, F: WrappedFormat<S> + 'static> Qcow2<S, F> {
9 pub(super) async fn read_compressed_cluster(
15 &self,
16 buf: &mut [u8],
17 compressed_offset: HostOffset,
18 compressed_length: u64,
19 ) -> io::Result<()> {
20 debug_assert!(buf.len() == self.header.cluster_size());
21
22 let storage = self.storage();
23
24 let compressed_length = compressed_length.try_into().map_err(io::Error::other)?;
26 let mut compressed_buf = IoBuffer::new(compressed_length, storage.mem_align())?;
27 storage
28 .read(&mut compressed_buf, compressed_offset.0)
29 .await?;
30
31 let mut dec_ox = DecompressorOxide::new();
32 let (status, _read, written) =
33 inflate(&mut dec_ox, compressed_buf.as_ref().into_slice(), buf, 0, 0);
34
35 if status != TINFLStatus::Done && status != TINFLStatus::HasMoreOutput {
38 return Err(io::Error::other(format!(
39 "Failed to decompress cluster (host offset {compressed_offset}+{compressed_length}): {status:?}",
40 )));
41 }
42 if written < buf.len() {
43 return Err(io::Error::other(format!(
44 "Failed to decompress cluster (host offset {compressed_offset}+{compressed_length}): Decompressed {written} bytes, expected {}",
45 buf.len(),
46 )));
47 }
48
49 Ok(())
50 }
51}