diff --git a/src/decoder/image.rs b/src/decoder/image.rs index 2ffa77c..2b8c035 100644 --- a/src/decoder/image.rs +++ b/src/decoder/image.rs @@ -1204,7 +1204,7 @@ impl Image { let mut packed = vec![0u8; chunk_row_bytes]; for row in buf.chunks_mut(layout.row_stride).take(data_dims.1 as usize) { - reader.read_samples(&mut packed)?; + reader.read_exact(&mut packed)?; let out_row = &mut row[..data_row_bytes]; unpack_bits(&packed, out_row, tiff_bps, samples_per_data_row, out_bps); @@ -1238,7 +1238,7 @@ impl Image { } else if is_output_chunk_rows && is_all_bits { // Here we can read directly into the output buffer itself. let tile = &mut buf[..chunk_row_bytes * data_dims.1 as usize]; - reader.read_samples(tile)?; + reader.read_exact(tile)?; for row in tile.chunks_mut(chunk_row_bytes) { super::fix_endianness_and_predict( @@ -1272,7 +1272,7 @@ impl Image { // this case is handled specially when needed. let mut encoded = vec![0u8; chunk_row_bytes]; for row in buf.chunks_mut(layout.row_stride).take(data_dims.1 as usize) { - reader.read_samples(&mut encoded)?; + reader.read_exact(&mut encoded)?; let row = &mut row[..data_row_bytes]; match color_type.bit_depth() { @@ -1313,7 +1313,7 @@ impl Image { let skip = u64::try_from(chunk_row_bytes - data_row_bytes)?; reader.read_padded_samples(&mut row[..used], skip)?; } else { - reader.read_samples(&mut row[..used])?; + reader.read_exact(&mut row[..used])?; } super::fix_endianness_and_predict( @@ -1371,7 +1371,7 @@ impl Image { // width, and writing their horizontal padding would spill into the following // output row (and predict/invert would run past the chunk's own columns). let row = &mut row[..data_row_bytes]; - reader.read_samples(&mut encoded)?; + reader.read_exact(&mut encoded)?; Self::compact_photometric_bytes(&mut encoded, row, &photo_range); diff --git a/src/decoder/stream.rs b/src/decoder/stream.rs index 71e8937..326ba67 100644 --- a/src/decoder/stream.rs +++ b/src/decoder/stream.rs @@ -124,6 +124,9 @@ impl EndianReader { /// A variant of `io::Read` that takes one block to the end. /// +/// This is derived from `Read` so that any special optimization done by `std` (or any nightly crate +/// for that matter) surely remains usable. +/// /// We want our decompression engines to be much more specialized than the standard library trait. /// Firstly there is more information available to communicate (the tiff Type, known decompressed /// size, …) and secondly they can potentially *reset*. This could be solved with an extension trait @@ -134,9 +137,7 @@ impl EndianReader { /// discarding data *after* it is put into the output buffer. Yet, for some decompression that write /// alone is considerable work where it could simply skip bits more efficiently. So the reader would /// likely want to know about a sample mask. -pub trait ReadSamples { - fn read_samples(&mut self, buf: &mut [u8]) -> io::Result<()>; - +pub trait ReadSamples: Read { /// Read a row of samples and throw away some additional padding samples at the end. /// /// This is automatically implemented for `Self: Read` as a copy into `io::Sink`. @@ -144,10 +145,6 @@ pub trait ReadSamples { } impl ReadSamples for R { - fn read_samples(&mut self, buf: &mut [u8]) -> io::Result<()> { - self.read_exact(buf) - } - fn read_padded_samples(&mut self, buf: &mut [u8], discard: u64) -> io::Result<()> { self.read_exact(buf)?; std::io::copy(&mut self.by_ref().take(discard), &mut std::io::sink())?;