Stand-alone size computation of Type

This commit is contained in:
A. Molzer authored and Aurelia Molzer committed 2025-11-03 20:29:48 +01:00
1 parent 2ccbe132e0
commit 2058b7f3ca
2 files changed
+58 -48

No files matched your search

+33 -48
View File
@@ -376,7 +376,10 @@ impl Entry {
} }
/// Returns a mem_reader for the offset/value field /// Returns a mem_reader for the offset/value field
fn r(&self, byte_order: ByteOrder) -> EndianReader<io::Cursor<Vec<u8>>> { pub(crate) fn offset_field_reader(
&self,
byte_order: ByteOrder,
) -> EndianReader<io::Cursor<Vec<u8>>> {
EndianReader::new(io::Cursor::new(self.offset.to_vec()), byte_order) EndianReader::new(io::Cursor::new(self.offset.to_vec()), byte_order)
} }
@@ -392,43 +395,25 @@ impl Entry {
} }
let bo = reader.byte_order; let bo = reader.byte_order;
let value_bytes = self.type_.value_bytes(self.count)?;
let tag_size = match self.type_ {
Type::BYTE | Type::SBYTE | Type::ASCII | Type::UNDEFINED => 1,
Type::SHORT | Type::SSHORT => 2,
Type::LONG | Type::SLONG | Type::FLOAT | Type::IFD => 4,
Type::LONG8
| Type::SLONG8
| Type::DOUBLE
| Type::RATIONAL
| Type::SRATIONAL
| Type::IFD8 => 8,
};
let value_bytes = match self.count.checked_mul(tag_size) {
Some(n) => n,
None => {
return Err(TiffError::LimitsExceeded);
}
};
// Case 2: there is one value. // Case 2: there is one value.
if self.count == 1 { if self.count == 1 {
// 2a: the value is 5-8 bytes and we're in BigTiff mode. // 2a: the value is 5-8 bytes and we're in BigTiff mode.
if bigtiff && value_bytes > 4 && value_bytes <= 8 { if bigtiff && value_bytes > 4 && value_bytes <= 8 {
return Ok(match self.type_ { return Ok(match self.type_ {
Type::LONG8 => UnsignedBig(self.r(bo).read_u64()?), Type::LONG8 => UnsignedBig(self.offset_field_reader(bo).read_u64()?),
Type::SLONG8 => SignedBig(self.r(bo).read_i64()?), Type::SLONG8 => SignedBig(self.offset_field_reader(bo).read_i64()?),
Type::DOUBLE => Double(self.r(bo).read_f64()?), Type::DOUBLE => Double(self.offset_field_reader(bo).read_f64()?),
Type::RATIONAL => { Type::RATIONAL => {
let mut r = self.r(bo); let mut r = self.offset_field_reader(bo);
Rational(r.read_u32()?, r.read_u32()?) Rational(r.read_u32()?, r.read_u32()?)
} }
Type::SRATIONAL => { Type::SRATIONAL => {
let mut r = self.r(bo); let mut r = self.offset_field_reader(bo);
SRational(r.read_i32()?, r.read_i32()?) SRational(r.read_i32()?, r.read_i32()?)
} }
Type::IFD8 => IfdBig(self.r(bo).read_u64()?), Type::IFD8 => IfdBig(self.offset_field_reader(bo).read_u64()?),
Type::BYTE Type::BYTE
| Type::SBYTE | Type::SBYTE
| Type::ASCII | Type::ASCII
@@ -447,11 +432,11 @@ impl Entry {
Type::BYTE => Byte(self.offset[0]), Type::BYTE => Byte(self.offset[0]),
Type::SBYTE => SignedByte(self.offset[0] as i8), Type::SBYTE => SignedByte(self.offset[0] as i8),
Type::UNDEFINED => Byte(self.offset[0]), Type::UNDEFINED => Byte(self.offset[0]),
Type::SHORT => Short(self.r(bo).read_u16()?), Type::SHORT => Short(self.offset_field_reader(bo).read_u16()?),
Type::SSHORT => SignedShort(self.r(bo).read_i16()?), Type::SSHORT => SignedShort(self.offset_field_reader(bo).read_i16()?),
Type::LONG => Unsigned(self.r(bo).read_u32()?), Type::LONG => Unsigned(self.offset_field_reader(bo).read_u32()?),
Type::SLONG => Signed(self.r(bo).read_i32()?), Type::SLONG => Signed(self.offset_field_reader(bo).read_i32()?),
Type::FLOAT => Float(self.r(bo).read_f32()?), Type::FLOAT => Float(self.offset_field_reader(bo).read_f32()?),
Type::ASCII => { Type::ASCII => {
if self.offset[0] == 0 { if self.offset[0] == 0 {
Ascii("".to_string()) Ascii("".to_string())
@@ -460,28 +445,28 @@ impl Entry {
} }
} }
Type::LONG8 => { Type::LONG8 => {
reader.goto_offset(self.r(bo).read_u32()?.into())?; reader.goto_offset(self.offset_field_reader(bo).read_u32()?.into())?;
UnsignedBig(reader.read_u64()?) UnsignedBig(reader.read_u64()?)
} }
Type::SLONG8 => { Type::SLONG8 => {
reader.goto_offset(self.r(bo).read_u32()?.into())?; reader.goto_offset(self.offset_field_reader(bo).read_u32()?.into())?;
SignedBig(reader.read_i64()?) SignedBig(reader.read_i64()?)
} }
Type::DOUBLE => { Type::DOUBLE => {
reader.goto_offset(self.r(bo).read_u32()?.into())?; reader.goto_offset(self.offset_field_reader(bo).read_u32()?.into())?;
Double(reader.read_f64()?) Double(reader.read_f64()?)
} }
Type::RATIONAL => { Type::RATIONAL => {
reader.goto_offset(self.r(bo).read_u32()?.into())?; reader.goto_offset(self.offset_field_reader(bo).read_u32()?.into())?;
Rational(reader.read_u32()?, reader.read_u32()?) Rational(reader.read_u32()?, reader.read_u32()?)
} }
Type::SRATIONAL => { Type::SRATIONAL => {
reader.goto_offset(self.r(bo).read_u32()?.into())?; reader.goto_offset(self.offset_field_reader(bo).read_u32()?.into())?;
SRational(reader.read_i32()?, reader.read_i32()?) SRational(reader.read_i32()?, reader.read_i32()?)
} }
Type::IFD => Ifd(self.r(bo).read_u32()?), Type::IFD => Ifd(self.offset_field_reader(bo).read_u32()?),
Type::IFD8 => { Type::IFD8 => {
reader.goto_offset(self.r(bo).read_u32()?.into())?; reader.goto_offset(self.offset_field_reader(bo).read_u32()?.into())?;
IfdBig(reader.read_u64()?) IfdBig(reader.read_u64()?)
} }
}); });
@@ -512,7 +497,7 @@ impl Entry {
)); ));
} }
Type::SHORT => { Type::SHORT => {
let mut r = self.r(bo); let mut r = self.offset_field_reader(bo);
let mut v = Vec::new(); let mut v = Vec::new();
for _ in 0..self.count { for _ in 0..self.count {
v.push(Short(r.read_u16()?)); v.push(Short(r.read_u16()?));
@@ -520,7 +505,7 @@ impl Entry {
return Ok(List(v)); return Ok(List(v));
} }
Type::SSHORT => { Type::SSHORT => {
let mut r = self.r(bo); let mut r = self.offset_field_reader(bo);
let mut v = Vec::new(); let mut v = Vec::new();
for _ in 0..self.count { for _ in 0..self.count {
v.push(SignedShort(r.read_i16()?)); v.push(SignedShort(r.read_i16()?));
@@ -528,7 +513,7 @@ impl Entry {
return Ok(List(v)); return Ok(List(v));
} }
Type::LONG => { Type::LONG => {
let mut r = self.r(bo); let mut r = self.offset_field_reader(bo);
let mut v = Vec::new(); let mut v = Vec::new();
for _ in 0..self.count { for _ in 0..self.count {
v.push(Unsigned(r.read_u32()?)); v.push(Unsigned(r.read_u32()?));
@@ -536,7 +521,7 @@ impl Entry {
return Ok(List(v)); return Ok(List(v));
} }
Type::SLONG => { Type::SLONG => {
let mut r = self.r(bo); let mut r = self.offset_field_reader(bo);
let mut v = Vec::new(); let mut v = Vec::new();
for _ in 0..self.count { for _ in 0..self.count {
v.push(Signed(r.read_i32()?)); v.push(Signed(r.read_i32()?));
@@ -544,7 +529,7 @@ impl Entry {
return Ok(List(v)); return Ok(List(v));
} }
Type::FLOAT => { Type::FLOAT => {
let mut r = self.r(bo); let mut r = self.offset_field_reader(bo);
let mut v = Vec::new(); let mut v = Vec::new();
for _ in 0..self.count { for _ in 0..self.count {
v.push(Float(r.read_f32()?)); v.push(Float(r.read_f32()?));
@@ -552,7 +537,7 @@ impl Entry {
return Ok(List(v)); return Ok(List(v));
} }
Type::IFD => { Type::IFD => {
let mut r = self.r(bo); let mut r = self.offset_field_reader(bo);
let mut v = Vec::new(); let mut v = Vec::new();
for _ in 0..self.count { for _ in 0..self.count {
v.push(Ifd(r.read_u32()?)); v.push(Ifd(r.read_u32()?));
@@ -636,9 +621,9 @@ impl Entry {
} }
if bigtiff { if bigtiff {
reader.goto_offset(self.r(bo).read_u64()?)? reader.goto_offset(self.offset_field_reader(bo).read_u64()?)?
} else { } else {
reader.goto_offset(self.r(bo).read_u32()?.into())? reader.goto_offset(self.offset_field_reader(bo).read_u32()?.into())?
} }
let mut out = vec![0; n]; let mut out = vec![0; n];
@@ -674,9 +659,9 @@ impl Entry {
let mut v = Vec::with_capacity(value_count); let mut v = Vec::with_capacity(value_count);
let offset = if bigtiff { let offset = if bigtiff {
self.r(bo).read_u64()? self.offset_field_reader(bo).read_u64()?
} else { } else {
self.r(bo).read_u32()?.into() self.offset_field_reader(bo).read_u32()?.into()
}; };
reader.goto_offset(offset)?; reader.goto_offset(offset)?;
+25
View File
@@ -193,6 +193,31 @@ pub enum Type(u16) {
} }
} }
impl Type {
pub(crate) fn byte_len(&self) -> u8 {
match *self {
Type::BYTE | Type::SBYTE | Type::ASCII | Type::UNDEFINED => 1,
Type::SHORT | Type::SSHORT => 2,
Type::LONG | Type::SLONG | Type::FLOAT | Type::IFD => 4,
Type::LONG8
| Type::SLONG8
| Type::DOUBLE
| Type::RATIONAL
| Type::SRATIONAL
| Type::IFD8 => 8,
}
}
pub(crate) fn value_bytes(&self, count: u64) -> Result<u64, crate::error::TiffError> {
let tag_size = u64::from(self.byte_len());
match count.checked_mul(tag_size) {
Some(n) => Ok(n),
None => Err(crate::error::TiffError::LimitsExceeded),
}
}
}
tags! { tags! {
/// See [TIFF compression tags](https://www.awaresystems.be/imaging/tiff/tifftags/compression.html) /// See [TIFF compression tags](https://www.awaresystems.be/imaging/tiff/tifftags/compression.html)
/// for reference. /// for reference.