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