From 6449b89d2ec3d8a9500586ec858e6ec7fc3933c4 Mon Sep 17 00:00:00 2001 From: Jonathan Behrens Date: Mon, 13 May 2024 18:04:27 -0700 Subject: [PATCH] Switch from SmartReader to EndianReader --- src/decoder/ifd.rs | 24 +++---- src/decoder/image.rs | 4 +- src/decoder/mod.rs | 32 ++++----- src/decoder/stream.rs | 132 +++++++++++++------------------------- src/decoder/tag_reader.rs | 4 +- 5 files changed, 78 insertions(+), 118 deletions(-) diff --git a/src/decoder/ifd.rs b/src/decoder/ifd.rs index 55775a0e..554ebd58 100644 --- a/src/decoder/ifd.rs +++ b/src/decoder/ifd.rs @@ -5,7 +5,7 @@ use std::io::{self, Read, Seek}; use std::mem; use std::str; -use super::stream::{ByteOrder, EndianReader, SmartReader}; +use super::stream::{ByteOrder, EndianReader}; use crate::tags::{Tag, Type}; use crate::{TiffError, TiffFormatError, TiffResult}; @@ -332,22 +332,22 @@ impl Entry { } /// Returns a mem_reader for the offset/value field - fn r(&self, byte_order: ByteOrder) -> SmartReader>> { - SmartReader::wrap(io::Cursor::new(self.offset.to_vec()), byte_order) + fn r(&self, byte_order: ByteOrder) -> EndianReader>> { + EndianReader::new(io::Cursor::new(self.offset.to_vec()), byte_order) } - pub fn val( + pub(crate) fn val( &self, limits: &super::Limits, bigtiff: bool, - reader: &mut SmartReader, + reader: &mut EndianReader, ) -> TiffResult { // Case 1: there are no values so we can return immediately. if self.count == 0 { return Ok(List(Vec::new())); } - let bo = reader.byte_order(); + let bo = reader.byte_order; let tag_size = match self.type_ { Type::BYTE | Type::SBYTE | Type::ASCII | Type::UNDEFINED => 1, @@ -450,7 +450,7 @@ impl Entry { Type::SBYTE => return offset_to_sbytes(self.count as usize, self), Type::ASCII => { let mut buf = vec![0; self.count as usize]; - self.r(bo).read_exact(&mut buf)?; + buf.copy_from_slice(&self.offset[..self.count as usize]); if buf.is_ascii() && buf.ends_with(&[0]) { let v = str::from_utf8(&buf)?; let v = v.trim_matches(char::from(0)); @@ -532,7 +532,7 @@ impl Entry { // at a different endianess of file/computer. Type::BYTE => self.decode_offset(self.count, bo, bigtiff, limits, reader, |reader| { let mut buf = [0; 1]; - reader.read_exact(&mut buf)?; + reader.inner().read_exact(&mut buf)?; Ok(UnsignedBig(u64::from(buf[0]))) }), Type::SBYTE => self.decode_offset(self.count, bo, bigtiff, limits, reader, |reader| { @@ -581,7 +581,7 @@ impl Entry { Type::UNDEFINED => { self.decode_offset(self.count, bo, bigtiff, limits, reader, |reader| { let mut buf = [0; 1]; - reader.read_exact(&mut buf)?; + reader.inner().read_exact(&mut buf)?; Ok(Byte(buf[0])) }) } @@ -598,7 +598,7 @@ impl Entry { } let mut out = vec![0; n]; - reader.read_exact(&mut out)?; + reader.inner().read_exact(&mut out)?; // Strings may be null-terminated, so we trim anything downstream of the null byte if let Some(first) = out.iter().position(|&b| b == 0) { out.truncate(first); @@ -615,12 +615,12 @@ impl Entry { bo: ByteOrder, bigtiff: bool, limits: &super::Limits, - reader: &mut SmartReader, + reader: &mut EndianReader, decode_fn: F, ) -> TiffResult where R: Read + Seek, - F: Fn(&mut SmartReader) -> TiffResult, + F: Fn(&mut EndianReader) -> TiffResult, { let value_count = usize::try_from(value_count)?; if value_count > limits.decoding_buffer_size / mem::size_of::() { diff --git a/src/decoder/image.rs b/src/decoder/image.rs index af206787..9f8c9857 100644 --- a/src/decoder/image.rs +++ b/src/decoder/image.rs @@ -2,7 +2,7 @@ use super::ifd::{Directory, Value}; use super::stream::{ByteOrder, DeflateReader, LZWReader, PackBitsReader}; use super::tag_reader::TagReader; use super::{fp_predict_f32, fp_predict_f64, DecodingBuffer, Limits}; -use super::{stream::SmartReader, ChunkType}; +use super::{stream::EndianReader, ChunkType}; use crate::tags::{ CompressionMethod, PhotometricInterpretation, PlanarConfiguration, Predictor, SampleFormat, Tag, }; @@ -81,7 +81,7 @@ pub(crate) struct Image { impl Image { pub fn from_reader( - reader: &mut SmartReader, + reader: &mut EndianReader, ifd: Directory, limits: &Limits, bigtiff: bool, diff --git a/src/decoder/mod.rs b/src/decoder/mod.rs index 574caff7..838f4d3a 100644 --- a/src/decoder/mod.rs +++ b/src/decoder/mod.rs @@ -13,7 +13,7 @@ use crate::tags::{ Tag, Type, }; -use self::stream::{ByteOrder, EndianReader, SmartReader}; +use self::stream::{ByteOrder, EndianReader}; pub mod ifd; mod image; @@ -298,7 +298,7 @@ pub struct Decoder where R: Read + Seek, { - reader: SmartReader, + reader: EndianReader, bigtiff: bool, limits: Limits, next_ifd: Option, @@ -525,7 +525,7 @@ impl Decoder { )) } }; - let mut reader = SmartReader::wrap(r, byte_order); + let mut reader = EndianReader::new(r, byte_order); let bigtiff = match reader.read_u16()? { 42 => false, @@ -703,7 +703,7 @@ impl Decoder { #[inline] pub fn read_byte(&mut self) -> Result { let mut buf = [0; 1]; - self.reader.read_exact(&mut buf)?; + self.reader.inner().read_exact(&mut buf)?; Ok(buf[0]) } @@ -757,7 +757,7 @@ impl Decoder { #[inline] pub fn read_string(&mut self, length: usize) -> TiffResult { let mut out = vec![0; length]; - self.reader.read_exact(&mut out)?; + self.reader.inner().read_exact(&mut out)?; // Strings may be null-terminated, so we trim anything downstream of the null byte if let Some(first) = out.iter().position(|&b| b == 0) { out.truncate(first); @@ -774,7 +774,7 @@ impl Decoder { )); } let mut val = [0; 4]; - self.reader.read_exact(&mut val)?; + self.reader.inner().read_exact(&mut val)?; Ok(val) } @@ -782,7 +782,7 @@ impl Decoder { #[inline] pub fn read_offset_u64(&mut self) -> Result<[u8; 8], io::Error> { let mut val = [0; 8]; - self.reader.read_exact(&mut val)?; + self.reader.inner().read_exact(&mut val)?; Ok(val) } @@ -794,7 +794,7 @@ impl Decoder { #[inline] pub fn goto_offset_u64(&mut self, offset: u64) -> io::Result<()> { - self.reader.seek(io::SeekFrom::Start(offset)).map(|_| ()) + self.reader.goto_offset(offset) } /// Reads a IFD entry. @@ -805,7 +805,7 @@ impl Decoder { // Count 4 bytes // Value 4 bytes either a pointer the value itself fn read_entry( - reader: &mut SmartReader, + reader: &mut EndianReader, bigtiff: bool, ) -> TiffResult> { let tag = Tag::from_u16_exhaustive(reader.read_u16()?); @@ -822,13 +822,13 @@ impl Decoder { let mut offset = [0; 8]; let count = reader.read_u64()?; - reader.read_exact(&mut offset)?; + reader.inner().read_exact(&mut offset)?; ifd::Entry::new_u64(type_, count, offset) } else { let mut offset = [0; 4]; let count = reader.read_u32()?; - reader.read_exact(&mut offset)?; + reader.inner().read_exact(&mut offset)?; ifd::Entry::new(type_, count, offset) }; Ok(Some((tag, entry))) @@ -836,7 +836,7 @@ impl Decoder { /// Reads the IFD starting at the indicated location. fn read_ifd( - reader: &mut SmartReader, + reader: &mut EndianReader, bigtiff: bool, ifd_location: u64, ) -> TiffResult<(Directory, Option)> { @@ -1038,12 +1038,12 @@ impl Decoder { output_width: usize, ) -> TiffResult<()> { let offset = self.image.chunk_file_range(chunk_index)?.0; - self.goto_offset_u64(offset)?; + self.reader.goto_offset(offset)?; let byte_order = self.reader.byte_order; self.image.expand_chunk( - &mut self.reader, + self.reader.inner(), buffer.copy(), output_width, byte_order, @@ -1155,14 +1155,14 @@ impl Decoder { // * pass requested band as parameter // * collect bands to a RGB encoding result in case of RGB bands for chunk in 0..image_chunks { - self.goto_offset_u64(self.image().chunk_offsets[chunk])?; + self.reader.goto_offset(self.image().chunk_offsets[chunk])?; let x = chunk % chunks_across; let y = chunk / chunks_across; let buffer_offset = y * strip_samples + x * chunk_dimensions.0 as usize * samples; let byte_order = self.reader.byte_order; self.image.expand_chunk( - &mut self.reader, + self.reader.inner(), result.as_buffer(buffer_offset).copy(), width as usize, byte_order, diff --git a/src/decoder/stream.rs b/src/decoder/stream.rs index 8a995b09..3718e34b 100644 --- a/src/decoder/stream.rs +++ b/src/decoder/stream.rs @@ -12,16 +12,32 @@ pub enum ByteOrder { } /// Reader that is aware of the byte order. -pub trait EndianReader: Read { - /// Byte order that should be adhered to - fn byte_order(&self) -> ByteOrder; +#[derive(Debug)] +pub struct EndianReader { + reader: R, + pub(crate) byte_order: ByteOrder, +} + +impl EndianReader { + pub fn new(reader: R, byte_order: ByteOrder) -> Self { + Self { reader, byte_order } + } + + pub fn inner(&mut self) -> &mut R { + &mut self.reader + } + + pub fn goto_offset(&mut self, offset: u64) -> io::Result<()> { + self.reader.seek(io::SeekFrom::Start(offset))?; + Ok(()) + } /// Reads an u16 #[inline(always)] - fn read_u16(&mut self) -> Result { + pub fn read_u16(&mut self) -> Result { let mut n = [0u8; 2]; - self.read_exact(&mut n)?; - Ok(match self.byte_order() { + self.reader.read_exact(&mut n)?; + Ok(match self.byte_order { ByteOrder::LittleEndian => u16::from_le_bytes(n), ByteOrder::BigEndian => u16::from_be_bytes(n), }) @@ -29,10 +45,10 @@ pub trait EndianReader: Read { /// Reads an i8 #[inline(always)] - fn read_i8(&mut self) -> Result { + pub fn read_i8(&mut self) -> Result { let mut n = [0u8; 1]; - self.read_exact(&mut n)?; - Ok(match self.byte_order() { + self.reader.read_exact(&mut n)?; + Ok(match self.byte_order { ByteOrder::LittleEndian => i8::from_le_bytes(n), ByteOrder::BigEndian => i8::from_be_bytes(n), }) @@ -40,10 +56,10 @@ pub trait EndianReader: Read { /// Reads an i16 #[inline(always)] - fn read_i16(&mut self) -> Result { + pub fn read_i16(&mut self) -> Result { let mut n = [0u8; 2]; - self.read_exact(&mut n)?; - Ok(match self.byte_order() { + self.reader.read_exact(&mut n)?; + Ok(match self.byte_order { ByteOrder::LittleEndian => i16::from_le_bytes(n), ByteOrder::BigEndian => i16::from_be_bytes(n), }) @@ -51,10 +67,10 @@ pub trait EndianReader: Read { /// Reads an u32 #[inline(always)] - fn read_u32(&mut self) -> Result { + pub fn read_u32(&mut self) -> Result { let mut n = [0u8; 4]; - self.read_exact(&mut n)?; - Ok(match self.byte_order() { + self.reader.read_exact(&mut n)?; + Ok(match self.byte_order { ByteOrder::LittleEndian => u32::from_le_bytes(n), ByteOrder::BigEndian => u32::from_be_bytes(n), }) @@ -62,10 +78,10 @@ pub trait EndianReader: Read { /// Reads an i32 #[inline(always)] - fn read_i32(&mut self) -> Result { + pub fn read_i32(&mut self) -> Result { let mut n = [0u8; 4]; - self.read_exact(&mut n)?; - Ok(match self.byte_order() { + self.reader.read_exact(&mut n)?; + Ok(match self.byte_order { ByteOrder::LittleEndian => i32::from_le_bytes(n), ByteOrder::BigEndian => i32::from_be_bytes(n), }) @@ -73,10 +89,10 @@ pub trait EndianReader: Read { /// Reads an u64 #[inline(always)] - fn read_u64(&mut self) -> Result { + pub fn read_u64(&mut self) -> Result { let mut n = [0u8; 8]; - self.read_exact(&mut n)?; - Ok(match self.byte_order() { + self.reader.read_exact(&mut n)?; + Ok(match self.byte_order { ByteOrder::LittleEndian => u64::from_le_bytes(n), ByteOrder::BigEndian => u64::from_be_bytes(n), }) @@ -84,10 +100,10 @@ pub trait EndianReader: Read { /// Reads an i64 #[inline(always)] - fn read_i64(&mut self) -> Result { + pub fn read_i64(&mut self) -> Result { let mut n = [0u8; 8]; - self.read_exact(&mut n)?; - Ok(match self.byte_order() { + self.reader.read_exact(&mut n)?; + Ok(match self.byte_order { ByteOrder::LittleEndian => i64::from_le_bytes(n), ByteOrder::BigEndian => i64::from_be_bytes(n), }) @@ -95,10 +111,10 @@ pub trait EndianReader: Read { /// Reads an f32 #[inline(always)] - fn read_f32(&mut self) -> Result { + pub fn read_f32(&mut self) -> Result { let mut n = [0u8; 4]; - self.read_exact(&mut n)?; - Ok(f32::from_bits(match self.byte_order() { + self.reader.read_exact(&mut n)?; + Ok(f32::from_bits(match self.byte_order { ByteOrder::LittleEndian => u32::from_le_bytes(n), ByteOrder::BigEndian => u32::from_be_bytes(n), })) @@ -106,10 +122,10 @@ pub trait EndianReader: Read { /// Reads an f64 #[inline(always)] - fn read_f64(&mut self) -> Result { + pub fn read_f64(&mut self) -> Result { let mut n = [0u8; 8]; - self.read_exact(&mut n)?; - Ok(f64::from_bits(match self.byte_order() { + self.reader.read_exact(&mut n)?; + Ok(f64::from_bits(match self.byte_order { ByteOrder::LittleEndian => u64::from_le_bytes(n), ByteOrder::BigEndian => u64::from_be_bytes(n), })) @@ -252,62 +268,6 @@ impl Read for PackBitsReader { } } -/// -/// ## SmartReader Reader -/// - -/// Reader that is aware of the byte order. -#[derive(Debug)] -pub struct SmartReader -where - R: Read, -{ - reader: R, - pub byte_order: ByteOrder, -} - -impl SmartReader -where - R: Read, -{ - /// Wraps a reader - pub fn wrap(reader: R, byte_order: ByteOrder) -> SmartReader { - SmartReader { reader, byte_order } - } - pub fn into_inner(self) -> R { - self.reader - } -} -impl SmartReader { - pub fn goto_offset(&mut self, offset: u64) -> io::Result<()> { - self.seek(io::SeekFrom::Start(offset)).map(|_| ()) - } -} - -impl EndianReader for SmartReader -where - R: Read, -{ - #[inline(always)] - fn byte_order(&self) -> ByteOrder { - self.byte_order - } -} - -impl Read for SmartReader { - #[inline] - fn read(&mut self, buf: &mut [u8]) -> io::Result { - self.reader.read(buf) - } -} - -impl Seek for SmartReader { - #[inline] - fn seek(&mut self, pos: io::SeekFrom) -> io::Result { - self.reader.seek(pos) - } -} - #[cfg(test)] mod test { use super::*; diff --git a/src/decoder/tag_reader.rs b/src/decoder/tag_reader.rs index 3ae2d176..549fa1d6 100644 --- a/src/decoder/tag_reader.rs +++ b/src/decoder/tag_reader.rs @@ -4,11 +4,11 @@ use crate::tags::Tag; use crate::{TiffError, TiffFormatError, TiffResult}; use super::ifd::{Directory, Value}; -use super::stream::SmartReader; +use super::stream::EndianReader; use super::Limits; pub(crate) struct TagReader<'a, R: Read + Seek> { - pub reader: &'a mut SmartReader, + pub reader: &'a mut EndianReader, pub ifd: &'a Directory, pub limits: &'a Limits, pub bigtiff: bool,