From 0de1261948c5a7e2708bc3866e5b8a099dd90303 Mon Sep 17 00:00:00 2001 From: "A. Molzer" <5550310+197g@users.noreply.github.com> Date: Thu, 27 Nov 2025 22:37:37 +0100 Subject: [PATCH] Simplify responsibility of testing buffer size --- src/decoder/mod.rs | 105 +++++++++++++-------------------------------- 1 file changed, 29 insertions(+), 76 deletions(-) diff --git a/src/decoder/mod.rs b/src/decoder/mod.rs index ae361ee..d7e8290 100644 --- a/src/decoder/mod.rs +++ b/src/decoder/mod.rs @@ -50,92 +50,60 @@ pub enum DecodingResult { } impl DecodingResult { - fn new_u8(size: usize, limits: &Limits) -> TiffResult { - if size > limits.decoding_buffer_size { + fn new( + size: usize, + limits: &Limits, + from_fn: fn(Vec) -> Self, + ) -> TiffResult { + if size > limits.decoding_buffer_size / core::mem::size_of::() { Err(TiffError::LimitsExceeded) } else { - Ok(DecodingResult::U8(vec![0; size])) + Ok(from_fn(vec![T::default(); size])) } } + fn new_u8(size: usize, limits: &Limits) -> TiffResult { + Self::new(size, limits, DecodingResult::U8) + } + fn new_u16(size: usize, limits: &Limits) -> TiffResult { - if size > limits.decoding_buffer_size / 2 { - Err(TiffError::LimitsExceeded) - } else { - Ok(DecodingResult::U16(vec![0; size])) - } + Self::new(size, limits, DecodingResult::U16) } fn new_u32(size: usize, limits: &Limits) -> TiffResult { - if size > limits.decoding_buffer_size / 4 { - Err(TiffError::LimitsExceeded) - } else { - Ok(DecodingResult::U32(vec![0; size])) - } + Self::new(size, limits, DecodingResult::U32) } fn new_u64(size: usize, limits: &Limits) -> TiffResult { - if size > limits.decoding_buffer_size / 8 { - Err(TiffError::LimitsExceeded) - } else { - Ok(DecodingResult::U64(vec![0; size])) - } + Self::new(size, limits, DecodingResult::U64) } fn new_f32(size: usize, limits: &Limits) -> TiffResult { - if size > limits.decoding_buffer_size / std::mem::size_of::() { - Err(TiffError::LimitsExceeded) - } else { - Ok(DecodingResult::F32(vec![0.0; size])) - } + Self::new(size, limits, DecodingResult::F32) } fn new_f64(size: usize, limits: &Limits) -> TiffResult { - if size > limits.decoding_buffer_size / std::mem::size_of::() { - Err(TiffError::LimitsExceeded) - } else { - Ok(DecodingResult::F64(vec![0.0; size])) - } + Self::new(size, limits, DecodingResult::F64) } fn new_f16(size: usize, limits: &Limits) -> TiffResult { - if size > limits.decoding_buffer_size / std::mem::size_of::() { - Err(TiffError::LimitsExceeded) - } else { - Ok(DecodingResult::F16(vec![f16::ZERO; size])) - } + Self::new(size, limits, DecodingResult::F16) } fn new_i8(size: usize, limits: &Limits) -> TiffResult { - if size > limits.decoding_buffer_size / std::mem::size_of::() { - Err(TiffError::LimitsExceeded) - } else { - Ok(DecodingResult::I8(vec![0; size])) - } + Self::new(size, limits, DecodingResult::I8) } fn new_i16(size: usize, limits: &Limits) -> TiffResult { - if size > limits.decoding_buffer_size / 2 { - Err(TiffError::LimitsExceeded) - } else { - Ok(DecodingResult::I16(vec![0; size])) - } + Self::new(size, limits, DecodingResult::I16) } fn new_i32(size: usize, limits: &Limits) -> TiffResult { - if size > limits.decoding_buffer_size / 4 { - Err(TiffError::LimitsExceeded) - } else { - Ok(DecodingResult::I32(vec![0; size])) - } + Self::new(size, limits, DecodingResult::I32) } fn new_i64(size: usize, limits: &Limits) -> TiffResult { - if size > limits.decoding_buffer_size / 8 { - Err(TiffError::LimitsExceeded) - } else { - Ok(DecodingResult::I64(vec![0; size])) - } + Self::new(size, limits, DecodingResult::I64) } pub fn as_buffer(&mut self, start: usize) -> DecodingBuffer<'_> { @@ -233,13 +201,15 @@ impl BufferLayoutPreference { complete_len: layout.total_bytes, } } +} +impl image::ReadoutLayout { #[inline(always)] - fn assert_min_layout(self, buffer: &[T]) -> TiffResult<()> { - if core::mem::size_of_val(buffer) < self.len { + fn assert_min_layout(&self, buffer: &[T]) -> TiffResult<()> { + if core::mem::size_of_val(buffer) < self.plane_stride { Err(TiffError::UsageError( UsageError::InsufficientOutputBufferSize { - needed: self.len, + needed: self.plane_stride, provided: buffer.len(), }, )) @@ -302,21 +272,6 @@ impl DecodingExtent { } .map_err(overflow) } - - #[inline(always)] - fn assert_min_layout(self, buffer: &[T]) -> TiffResult<()> { - let needed_bytes = self.preferred_layout()?.size(); - if core::mem::size_of_val(buffer) < needed_bytes { - Err(TiffError::UsageError( - UsageError::InsufficientOutputBufferSize { - needed: needed_bytes, - provided: buffer.len(), - }, - )) - } else { - Ok(()) - } - } } #[derive(Debug, Copy, Clone, PartialEq)] @@ -1222,8 +1177,7 @@ impl Decoder { let (width, height) = self.image().chunk_data_dimensions(chunk_index)?; let layout = self.image().readout_for_size(width, height)?; - let extent = self.result_extent(&layout, 0..1)?; - extent.assert_min_layout(buffer)?; + layout.assert_min_layout(buffer)?; self.read_chunk_to_bytes(buffer, chunk_index, &layout)?; @@ -1305,8 +1259,7 @@ impl Decoder { ref readout, } = readout.to_plane_layout()?; - let preference = BufferLayoutPreference::from_planes(layout); - preference.assert_min_layout(buffer)?; + layout.readout.assert_min_layout(buffer)?; // Note: with differently sized planes this is dependent on the plane. let last_plane_start = buffer.len().checked_sub(readout.plane_stride); @@ -1340,7 +1293,7 @@ impl Decoder { self.image.expand_chunk( &mut self.value_reader, &mut buffer[plane_offset..][buffer_offset..], - &readout, + readout, chunk, )?; }