use std::collections::HashMap;
use std::convert::{TryFrom, TryInto};
use std::io::{self, Read, Seek};
use std::mem;
use super::stream::{ByteOrder, EndianReader, SmartReader};
use crate::tags::{Tag, Type};
use crate::{TiffError, TiffFormatError, TiffResult};
use self::Value::{
Ascii, Byte, Double, Float, List, Rational, RationalBig, SRational, SRationalBig, Short,
Signed, SignedBig, Unsigned, UnsignedBig,
};
#[allow(unused_qualifications)]
#[derive(Debug, Clone, PartialEq)]
pub enum Value {
Byte(u8),
Short(u16),
Signed(i32),
SignedBig(i64),
Unsigned(u32),
UnsignedBig(u64),
Float(f32),
Double(f64),
List(Vec<Value>),
Rational(u32, u32),
RationalBig(u64, u64),
SRational(i32, i32),
SRationalBig(i64, i64),
Ascii(String),
#[doc(hidden)]
__NonExhaustive,
}
impl Value {
pub fn into_u8(self) -> TiffResult<u8> {
match self {
Byte(val) => Ok(val),
val => Err(TiffError::FormatError(TiffFormatError::ByteExpected(val))),
}
}
pub fn into_u16(self) -> TiffResult<u16> {
match self {
Short(val) => Ok(val),
Unsigned(val) => Ok(u16::try_from(val)?),
UnsignedBig(val) => Ok(u16::try_from(val)?),
val => Err(TiffError::FormatError(
TiffFormatError::UnsignedIntegerExpected(val),
)),
}
}
pub fn into_u32(self) -> TiffResult<u32> {
match self {
Short(val) => Ok(val.into()),
Unsigned(val) => Ok(val),
UnsignedBig(val) => Ok(u32::try_from(val)?),
val => Err(TiffError::FormatError(
TiffFormatError::UnsignedIntegerExpected(val),
)),
}
}
pub fn into_i32(self) -> TiffResult<i32> {
match self {
Signed(val) => Ok(val),
SignedBig(val) => Ok(i32::try_from(val)?),
val => Err(TiffError::FormatError(
TiffFormatError::SignedIntegerExpected(val),
)),
}
}
pub fn into_u64(self) -> TiffResult<u64> {
match self {
Short(val) => Ok(val.into()),
Unsigned(val) => Ok(val.into()),
UnsignedBig(val) => Ok(val),
val => Err(TiffError::FormatError(
TiffFormatError::UnsignedIntegerExpected(val),
)),
}
}
pub fn into_i64(self) -> TiffResult<i64> {
match self {
Signed(val) => Ok(val.into()),
SignedBig(val) => Ok(val),
val => Err(TiffError::FormatError(
TiffFormatError::SignedIntegerExpected(val),
)),
}
}
pub fn into_f32(self) -> TiffResult<f32> {
match self {
Float(val) => Ok(val),
val => Err(TiffError::FormatError(
TiffFormatError::SignedIntegerExpected(val),
)),
}
}
pub fn into_f64(self) -> TiffResult<f64> {
match self {
Double(val) => Ok(val),
val => Err(TiffError::FormatError(
TiffFormatError::SignedIntegerExpected(val),
)),
}
}
pub fn into_string(self) -> TiffResult<String> {
match self {
Ascii(val) => Ok(val),
val => Err(TiffError::FormatError(
TiffFormatError::SignedIntegerExpected(val),
)),
}
}
pub fn into_u32_vec(self) -> TiffResult<Vec<u32>> {
match self {
List(vec) => {
let mut new_vec = Vec::with_capacity(vec.len());
for v in vec {
new_vec.push(v.into_u32()?)
}
Ok(new_vec)
}
Unsigned(val) => Ok(vec![val]),
UnsignedBig(val) => Ok(vec![u32::try_from(val)?]),
Rational(numerator, denominator) => Ok(vec![numerator, denominator]),
RationalBig(numerator, denominator) => {
Ok(vec![u32::try_from(numerator)?, u32::try_from(denominator)?])
}
Ascii(val) => Ok(val.chars().map(u32::from).collect()),
val => Err(TiffError::FormatError(
TiffFormatError::UnsignedIntegerExpected(val),
)),
}
}
pub fn into_u8_vec(self) -> TiffResult<Vec<u8>> {
match self {
List(vec) => {
let mut new_vec = Vec::with_capacity(vec.len());
for v in vec {
new_vec.push(v.into_u8()?)
}
Ok(new_vec)
}
Byte(val) => Ok(vec![val]),
val => Err(TiffError::FormatError(
TiffFormatError::UnsignedIntegerExpected(val),
)),
}
}
pub fn into_u16_vec(self) -> TiffResult<Vec<u16>> {
match self {
List(vec) => {
let mut new_vec = Vec::with_capacity(vec.len());
for v in vec {
new_vec.push(v.into_u16()?)
}
Ok(new_vec)
}
Short(val) => Ok(vec![val]),
val => Err(TiffError::FormatError(
TiffFormatError::UnsignedIntegerExpected(val),
)),
}
}
pub fn into_i32_vec(self) -> TiffResult<Vec<i32>> {
match self {
List(vec) => {
let mut new_vec = Vec::with_capacity(vec.len());
for v in vec {
match v {
SRational(numerator, denominator) => {
new_vec.push(numerator);
new_vec.push(denominator);
}
SRationalBig(numerator, denominator) => {
new_vec.push(i32::try_from(numerator)?);
new_vec.push(i32::try_from(denominator)?);
}
_ => new_vec.push(v.into_i32()?),
}
}
Ok(new_vec)
}
Signed(val) => Ok(vec![val]),
SignedBig(val) => Ok(vec![i32::try_from(val)?]),
SRational(numerator, denominator) => Ok(vec![numerator, denominator]),
SRationalBig(numerator, denominator) => {
Ok(vec![i32::try_from(numerator)?, i32::try_from(denominator)?])
}
val => Err(TiffError::FormatError(
TiffFormatError::SignedIntegerExpected(val),
)),
}
}
pub fn into_f32_vec(self) -> TiffResult<Vec<f32>> {
match self {
List(vec) => {
let mut new_vec = Vec::with_capacity(vec.len());
for v in vec {
new_vec.push(v.into_f32()?)
}
Ok(new_vec)
}
Float(val) => Ok(vec![val]),
val => Err(TiffError::FormatError(
TiffFormatError::UnsignedIntegerExpected(val),
)),
}
}
pub fn into_f64_vec(self) -> TiffResult<Vec<f64>> {
match self {
List(vec) => {
let mut new_vec = Vec::with_capacity(vec.len());
for v in vec {
new_vec.push(v.into_f64()?)
}
Ok(new_vec)
}
Double(val) => Ok(vec![val]),
val => Err(TiffError::FormatError(
TiffFormatError::UnsignedIntegerExpected(val),
)),
}
}
pub fn into_u64_vec(self) -> TiffResult<Vec<u64>> {
match self {
List(vec) => {
let mut new_vec = Vec::with_capacity(vec.len());
for v in vec {
new_vec.push(v.into_u64()?)
}
Ok(new_vec)
}
Unsigned(val) => Ok(vec![val.into()]),
UnsignedBig(val) => Ok(vec![val]),
Rational(numerator, denominator) => Ok(vec![numerator.into(), denominator.into()]),
RationalBig(numerator, denominator) => Ok(vec![numerator, denominator]),
Ascii(val) => Ok(val.chars().map(u32::from).map(u64::from).collect()),
val => Err(TiffError::FormatError(
TiffFormatError::UnsignedIntegerExpected(val),
)),
}
}
pub fn into_i64_vec(self) -> TiffResult<Vec<i64>> {
match self {
List(vec) => {
let mut new_vec = Vec::with_capacity(vec.len());
for v in vec {
match v {
SRational(numerator, denominator) => {
new_vec.push(numerator.into());
new_vec.push(denominator.into());
}
SRationalBig(numerator, denominator) => {
new_vec.push(numerator);
new_vec.push(denominator);
}
_ => new_vec.push(v.into_i64()?),
}
}
Ok(new_vec)
}
Signed(val) => Ok(vec![val.into()]),
SignedBig(val) => Ok(vec![val]),
SRational(numerator, denominator) => Ok(vec![numerator.into(), denominator.into()]),
SRationalBig(numerator, denominator) => Ok(vec![numerator, denominator]),
val => Err(TiffError::FormatError(
TiffFormatError::SignedIntegerExpected(val),
)),
}
}
}
#[derive(Clone)]
pub struct Entry {
type_: Type,
count: u64,
offset: [u8; 8],
}
impl ::std::fmt::Debug for Entry {
fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
fmt.write_str(&format!(
"Entry {{ type_: {:?}, count: {:?}, offset: {:?} }}",
self.type_, self.count, &self.offset
))
}
}
impl Entry {
pub fn new(type_: Type, count: u32, offset: [u8; 4]) -> Entry {
let mut offset = offset.to_vec();
offset.append(&mut vec![0; 4]);
Entry::new_u64(type_, count.into(), offset[..].try_into().unwrap())
}
pub fn new_u64(type_: Type, count: u64, offset: [u8; 8]) -> Entry {
Entry {
type_,
count,
offset,
}
}
fn r(&self, byte_order: ByteOrder) -> SmartReader<io::Cursor<Vec<u8>>> {
SmartReader::wrap(io::Cursor::new(self.offset.to_vec()), byte_order)
}
pub fn val<R: Read + Seek>(
&self,
limits: &super::Limits,
decoder: &mut super::Decoder<R>,
) -> TiffResult<Value> {
if self.count == 0 {
return Ok(List(Vec::new()));
}
let bo = decoder.byte_order();
let value_bytes = self.count
* match self.type_ {
Type::BYTE | Type::SBYTE | Type::ASCII | Type::UNDEFINED => 1,
Type::SHORT | Type::SSHORT => 2,
Type::LONG | Type::SLONG | Type::FLOAT => 4,
Type::LONG8 | Type::DOUBLE | Type::RATIONAL | Type::SRATIONAL => 8,
Type::__NonExhaustive => unreachable!(),
};
if self.count == 1 {
if decoder.bigtiff && value_bytes > 4 && value_bytes <= 8 {
return Ok(match self.type_ {
Type::LONG8 => UnsignedBig(self.r(bo).read_u64()?),
Type::DOUBLE => Double(self.r(bo).read_f64()?),
Type::RATIONAL => {
let mut r = self.r(bo);
Rational(r.read_u32()?, r.read_u32()?)
}
Type::SRATIONAL => {
let mut r = self.r(bo);
SRational(r.read_i32()?, r.read_i32()?)
}
Type::BYTE
| Type::SBYTE
| Type::ASCII
| Type::UNDEFINED
| Type::SHORT
| Type::SSHORT
| Type::LONG
| Type::SLONG
| Type::FLOAT => unreachable!(),
Type::__NonExhaustive => unreachable!(),
});
}
return Ok(match self.type_ {
Type::BYTE => Unsigned(u32::from(self.offset[0])),
Type::SBYTE => Signed(i32::from(self.offset[0] as i8)),
Type::UNDEFINED => Byte(self.offset[0]),
Type::SHORT => Unsigned(u32::from(self.r(bo).read_u16()?)),
Type::SSHORT => Signed(i32::from(self.r(bo).read_i16()?)),
Type::LONG => Unsigned(self.r(bo).read_u32()?),
Type::SLONG => Signed(self.r(bo).read_i32()?),
Type::FLOAT => Float(self.r(bo).read_f32()?),
Type::ASCII => {
if self.offset[0] == 0 {
Ascii("".to_string())
} else {
return Err(TiffError::FormatError(TiffFormatError::InvalidTag));
}
}
Type::LONG8 => {
decoder.goto_offset(self.r(bo).read_u32()?)?;
UnsignedBig(decoder.read_long8()?)
}
Type::DOUBLE => {
decoder.goto_offset(self.r(bo).read_u32()?)?;
Double(decoder.read_double()?)
}
Type::RATIONAL => {
decoder.goto_offset(self.r(bo).read_u32()?)?;
Rational(decoder.read_long()?, decoder.read_long()?)
}
Type::SRATIONAL => {
decoder.goto_offset(self.r(bo).read_u32()?)?;
SRational(decoder.read_slong()?, decoder.read_slong()?)
}
Type::__NonExhaustive => unreachable!(),
});
}
if value_bytes <= 4 || decoder.bigtiff && value_bytes <= 8 {
match self.type_ {
Type::BYTE => return Ok(offset_to_bytes(self.count as usize, self)?),
Type::SBYTE => return Ok(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)?;
let v = String::from_utf8(buf)?;
let v = v.trim_matches(char::from(0));
return Ok(Ascii(v.into()));
}
Type::UNDEFINED => {
return Ok(List(
self.offset[0..self.count as usize]
.iter()
.map(|&b| Byte(b))
.collect(),
));
}
Type::SHORT => {
let mut r = self.r(bo);
let mut v = Vec::new();
for _ in 0..self.count {
v.push(Short(r.read_u16()?));
}
return Ok(List(v));
}
Type::SSHORT => {
let mut r = self.r(bo);
let mut v = Vec::new();
for _ in 0..self.count {
v.push(Signed(i32::from(r.read_i16()?)));
}
return Ok(List(v));
}
Type::LONG => {
let mut r = self.r(bo);
let mut v = Vec::new();
for _ in 0..self.count {
v.push(Unsigned(r.read_u32()?));
}
return Ok(List(v));
}
Type::SLONG => {
let mut r = self.r(bo);
let mut v = Vec::new();
for _ in 0..self.count {
v.push(Signed(r.read_i32()?));
}
return Ok(List(v));
}
Type::FLOAT => {
let mut r = self.r(bo);
let mut v = Vec::new();
for _ in 0..self.count {
v.push(Float(r.read_f32()?));
}
return Ok(List(v));
}
Type::LONG8 | Type::RATIONAL | Type::SRATIONAL | Type::DOUBLE => unreachable!(),
Type::__NonExhaustive => unreachable!(),
}
}
match self.type_ {
Type::BYTE => self.decode_offset(self.count, bo, limits, decoder, |decoder| {
Ok(UnsignedBig(u64::from(decoder.read_byte()?)))
}),
Type::SBYTE => self.decode_offset(self.count, bo, limits, decoder, |decoder| {
Ok(SignedBig(i64::from(decoder.read_byte()? as i8)))
}),
Type::SHORT => self.decode_offset(self.count, bo, limits, decoder, |decoder| {
Ok(UnsignedBig(u64::from(decoder.read_short()?)))
}),
Type::SSHORT => self.decode_offset(self.count, bo, limits, decoder, |decoder| {
Ok(SignedBig(i64::from(decoder.read_sshort()?)))
}),
Type::LONG => self.decode_offset(self.count, bo, limits, decoder, |decoder| {
Ok(Unsigned(decoder.read_long()?))
}),
Type::SLONG => self.decode_offset(self.count, bo, limits, decoder, |decoder| {
Ok(Signed(decoder.read_slong()?))
}),
Type::FLOAT => self.decode_offset(self.count, bo, limits, decoder, |decoder| {
Ok(Float(decoder.read_float()?))
}),
Type::DOUBLE => self.decode_offset(self.count, bo, limits, decoder, |decoder| {
Ok(Double(decoder.read_double()?))
}),
Type::RATIONAL => self.decode_offset(self.count, bo, limits, decoder, |decoder| {
Ok(Rational(decoder.read_long()?, decoder.read_long()?))
}),
Type::SRATIONAL => self.decode_offset(self.count, bo, limits, decoder, |decoder| {
Ok(SRational(decoder.read_slong()?, decoder.read_slong()?))
}),
Type::LONG8 => self.decode_offset(self.count, bo, limits, decoder, |decoder| {
Ok(UnsignedBig(decoder.read_long8()?))
}),
Type::UNDEFINED => self.decode_offset(self.count, bo, limits, decoder, |decoder| {
Ok(Byte(u8::from(decoder.read_byte()?)))
}),
Type::ASCII => {
let n = usize::try_from(self.count)?;
if n > limits.decoding_buffer_size {
return Err(TiffError::LimitsExceeded);
}
if decoder.bigtiff {
decoder.goto_offset_u64(self.r(bo).read_u64()?)?
} else {
decoder.goto_offset(self.r(bo).read_u32()?)?
}
let string = decoder.read_string(n)?;
Ok(Ascii(string))
}
Type::__NonExhaustive => unreachable!(),
}
}
#[inline]
fn decode_offset<R, F>(
&self,
value_count: u64,
bo: ByteOrder,
limits: &super::Limits,
decoder: &mut super::Decoder<R>,
decode_fn: F,
) -> TiffResult<Value>
where
R: Read + Seek,
F: Fn(&mut super::Decoder<R>) -> TiffResult<Value>,
{
let value_count = usize::try_from(value_count)?;
if value_count > limits.decoding_buffer_size / mem::size_of::<Value>() {
return Err(TiffError::LimitsExceeded);
}
let mut v = Vec::with_capacity(value_count);
if decoder.bigtiff {
decoder.goto_offset_u64(self.r(bo).read_u64()?)?
} else {
decoder.goto_offset(self.r(bo).read_u32()?)?
}
for _ in 0..value_count {
v.push(decode_fn(decoder)?)
}
Ok(List(v))
}
}
#[inline]
fn offset_to_bytes(n: usize, entry: &Entry) -> TiffResult<Value> {
Ok(List(
entry.offset[0..n]
.iter()
.map(|&e| Unsigned(u32::from(e)))
.collect(),
))
}
#[inline]
fn offset_to_sbytes(n: usize, entry: &Entry) -> TiffResult<Value> {
Ok(List(
entry.offset[0..n]
.iter()
.map(|&e| Signed(i32::from(e as i8)))
.collect(),
))
}
pub type Directory = HashMap<Tag, Entry>;