Switch to quick_error and cleaner error messages (#269)

This commit is contained in:
Jonathan Behrens authored and GitHub committed 2025-06-09 19:10:12 -07:00
1 parent f44da4a00d
commit b5d8ee5f86
3 files changed
+170 -371

No files matched your search

+1
View File
@@ -22,6 +22,7 @@ weezl = "0.1.0"
jpeg = { package = "jpeg-decoder", version = "0.3.0", default-features = false } jpeg = { package = "jpeg-decoder", version = "0.3.0", default-features = false }
flate2 = "1.0.20" flate2 = "1.0.20"
zstd = { version = "0.13", optional = true } zstd = { version = "0.13", optional = true }
quick-error = "2.0.1"
[dev-dependencies] [dev-dependencies]
criterion = "0.3.1" criterion = "0.3.1"
+19 -49
View File
@@ -42,15 +42,13 @@ impl Value {
pub fn into_u8(self) -> TiffResult<u8> { pub fn into_u8(self) -> TiffResult<u8> {
match self { match self {
Byte(val) => Ok(val), Byte(val) => Ok(val),
val => Err(TiffError::FormatError(TiffFormatError::ByteExpected(val))), _ => Err(TiffError::FormatError(TiffFormatError::InvalidTypeForTag)),
} }
} }
pub fn into_i8(self) -> TiffResult<i8> { pub fn into_i8(self) -> TiffResult<i8> {
match self { match self {
SignedByte(val) => Ok(val), SignedByte(val) => Ok(val),
val => Err(TiffError::FormatError(TiffFormatError::SignedByteExpected( _ => Err(TiffError::FormatError(TiffFormatError::InvalidTypeForTag)),
val,
))),
} }
} }
@@ -60,7 +58,7 @@ impl Value {
Short(val) => Ok(val), Short(val) => Ok(val),
Unsigned(val) => Ok(u16::try_from(val)?), Unsigned(val) => Ok(u16::try_from(val)?),
UnsignedBig(val) => Ok(u16::try_from(val)?), UnsignedBig(val) => Ok(u16::try_from(val)?),
val => Err(TiffError::FormatError(TiffFormatError::ShortExpected(val))), _ => Err(TiffError::FormatError(TiffFormatError::InvalidTypeForTag)),
} }
} }
@@ -70,9 +68,7 @@ impl Value {
SignedShort(val) => Ok(val), SignedShort(val) => Ok(val),
Signed(val) => Ok(i16::try_from(val)?), Signed(val) => Ok(i16::try_from(val)?),
SignedBig(val) => Ok(i16::try_from(val)?), SignedBig(val) => Ok(i16::try_from(val)?),
val => Err(TiffError::FormatError( _ => Err(TiffError::FormatError(TiffFormatError::InvalidTypeForTag)),
TiffFormatError::SignedShortExpected(val),
)),
} }
} }
@@ -84,9 +80,7 @@ impl Value {
UnsignedBig(val) => Ok(u32::try_from(val)?), UnsignedBig(val) => Ok(u32::try_from(val)?),
Ifd(val) => Ok(val), Ifd(val) => Ok(val),
IfdBig(val) => Ok(u32::try_from(val)?), IfdBig(val) => Ok(u32::try_from(val)?),
val => Err(TiffError::FormatError( _ => Err(TiffError::FormatError(TiffFormatError::InvalidTypeForTag)),
TiffFormatError::UnsignedIntegerExpected(val),
)),
} }
} }
@@ -96,9 +90,7 @@ impl Value {
SignedShort(val) => Ok(val.into()), SignedShort(val) => Ok(val.into()),
Signed(val) => Ok(val), Signed(val) => Ok(val),
SignedBig(val) => Ok(i32::try_from(val)?), SignedBig(val) => Ok(i32::try_from(val)?),
val => Err(TiffError::FormatError( _ => Err(TiffError::FormatError(TiffFormatError::InvalidTypeForTag)),
TiffFormatError::SignedIntegerExpected(val),
)),
} }
} }
@@ -110,9 +102,7 @@ impl Value {
UnsignedBig(val) => Ok(val), UnsignedBig(val) => Ok(val),
Ifd(val) => Ok(val.into()), Ifd(val) => Ok(val.into()),
IfdBig(val) => Ok(val), IfdBig(val) => Ok(val),
val => Err(TiffError::FormatError( _ => Err(TiffError::FormatError(TiffFormatError::InvalidTypeForTag)),
TiffFormatError::UnsignedIntegerExpected(val),
)),
} }
} }
@@ -122,36 +112,28 @@ impl Value {
SignedShort(val) => Ok(val.into()), SignedShort(val) => Ok(val.into()),
Signed(val) => Ok(val.into()), Signed(val) => Ok(val.into()),
SignedBig(val) => Ok(val), SignedBig(val) => Ok(val),
val => Err(TiffError::FormatError( _ => Err(TiffError::FormatError(TiffFormatError::InvalidTypeForTag)),
TiffFormatError::SignedIntegerExpected(val),
)),
} }
} }
pub fn into_f32(self) -> TiffResult<f32> { pub fn into_f32(self) -> TiffResult<f32> {
match self { match self {
Float(val) => Ok(val), Float(val) => Ok(val),
val => Err(TiffError::FormatError( _ => Err(TiffError::FormatError(TiffFormatError::InvalidTypeForTag)),
TiffFormatError::SignedIntegerExpected(val),
)),
} }
} }
pub fn into_f64(self) -> TiffResult<f64> { pub fn into_f64(self) -> TiffResult<f64> {
match self { match self {
Double(val) => Ok(val), Double(val) => Ok(val),
val => Err(TiffError::FormatError( _ => Err(TiffError::FormatError(TiffFormatError::InvalidTypeForTag)),
TiffFormatError::SignedIntegerExpected(val),
)),
} }
} }
pub fn into_string(self) -> TiffResult<String> { pub fn into_string(self) -> TiffResult<String> {
match self { match self {
Ascii(val) => Ok(val), Ascii(val) => Ok(val),
val => Err(TiffError::FormatError( _ => Err(TiffError::FormatError(TiffFormatError::InvalidTypeForTag)),
TiffFormatError::SignedIntegerExpected(val),
)),
} }
} }
@@ -175,9 +157,7 @@ impl Value {
Ifd(val) => Ok(vec![val]), Ifd(val) => Ok(vec![val]),
IfdBig(val) => Ok(vec![u32::try_from(val)?]), IfdBig(val) => Ok(vec![u32::try_from(val)?]),
Ascii(val) => Ok(val.chars().map(u32::from).collect()), Ascii(val) => Ok(val.chars().map(u32::from).collect()),
val => Err(TiffError::FormatError( _ => Err(TiffError::FormatError(TiffFormatError::InvalidTypeForTag)),
TiffFormatError::UnsignedIntegerExpected(val),
)),
} }
} }
@@ -192,7 +172,7 @@ impl Value {
} }
Byte(val) => Ok(vec![val]), Byte(val) => Ok(vec![val]),
val => Err(TiffError::FormatError(TiffFormatError::ByteExpected(val))), _ => Err(TiffError::FormatError(TiffFormatError::InvalidTypeForTag)),
} }
} }
@@ -207,7 +187,7 @@ impl Value {
} }
Byte(val) => Ok(vec![val.into()]), Byte(val) => Ok(vec![val.into()]),
Short(val) => Ok(vec![val]), Short(val) => Ok(vec![val]),
val => Err(TiffError::FormatError(TiffFormatError::ShortExpected(val))), _ => Err(TiffError::FormatError(TiffFormatError::InvalidTypeForTag)),
} }
} }
@@ -238,9 +218,7 @@ impl Value {
SRationalBig(numerator, denominator) => { SRationalBig(numerator, denominator) => {
Ok(vec![i32::try_from(numerator)?, i32::try_from(denominator)?]) Ok(vec![i32::try_from(numerator)?, i32::try_from(denominator)?])
} }
val => Err(TiffError::FormatError( _ => Err(TiffError::FormatError(TiffFormatError::InvalidTypeForTag)),
TiffFormatError::SignedIntegerExpected(val),
)),
} }
} }
@@ -254,9 +232,7 @@ impl Value {
Ok(new_vec) Ok(new_vec)
} }
Float(val) => Ok(vec![val]), Float(val) => Ok(vec![val]),
val => Err(TiffError::FormatError( _ => Err(TiffError::FormatError(TiffFormatError::InvalidTypeForTag)),
TiffFormatError::UnsignedIntegerExpected(val),
)),
} }
} }
@@ -270,9 +246,7 @@ impl Value {
Ok(new_vec) Ok(new_vec)
} }
Double(val) => Ok(vec![val]), Double(val) => Ok(vec![val]),
val => Err(TiffError::FormatError( _ => Err(TiffError::FormatError(TiffFormatError::InvalidTypeForTag)),
TiffFormatError::UnsignedIntegerExpected(val),
)),
} }
} }
@@ -294,9 +268,7 @@ impl Value {
Ifd(val) => Ok(vec![val.into()]), Ifd(val) => Ok(vec![val.into()]),
IfdBig(val) => Ok(vec![val]), IfdBig(val) => Ok(vec![val]),
Ascii(val) => Ok(val.chars().map(u32::from).map(u64::from).collect()), Ascii(val) => Ok(val.chars().map(u32::from).map(u64::from).collect()),
val => Err(TiffError::FormatError( _ => Err(TiffError::FormatError(TiffFormatError::InvalidTypeForTag)),
TiffFormatError::UnsignedIntegerExpected(val),
)),
} }
} }
@@ -325,9 +297,7 @@ impl Value {
SignedBig(val) => Ok(vec![val]), SignedBig(val) => Ok(vec![val]),
SRational(numerator, denominator) => Ok(vec![numerator.into(), denominator.into()]), SRational(numerator, denominator) => Ok(vec![numerator.into(), denominator.into()]),
SRationalBig(numerator, denominator) => Ok(vec![numerator, denominator]), SRationalBig(numerator, denominator) => Ok(vec![numerator, denominator]),
val => Err(TiffError::FormatError( _ => Err(TiffError::FormatError(TiffFormatError::InvalidTypeForTag)),
TiffFormatError::SignedIntegerExpected(val),
)),
} }
} }
} }
+150 -322
View File
@@ -1,14 +1,11 @@
use std::error::Error;
use std::fmt;
use std::fmt::Display;
use std::io; use std::io;
use std::str; use std::str;
use std::string; use std::string;
use std::sync::Arc;
use jpeg::UnsupportedFeature; use jpeg::UnsupportedFeature;
use quick_error::quick_error;
use crate::decoder::{ifd::Value, ChunkType}; use crate::decoder::ChunkType;
use crate::tags::{ use crate::tags::{
CompressionMethod, PhotometricInterpretation, PlanarConfiguration, SampleFormat, Tag, CompressionMethod, PhotometricInterpretation, PlanarConfiguration, SampleFormat, Tag,
}; };
@@ -16,302 +13,186 @@ use crate::ColorType;
use crate::weezl::LzwError; use crate::weezl::LzwError;
/// Tiff error kinds. quick_error! {
#[derive(Debug)] /// Tiff error kinds.
pub enum TiffError { #[derive(Debug)]
pub enum TiffError {
/// The Image is not formatted properly. /// The Image is not formatted properly.
FormatError(TiffFormatError), FormatError(err: TiffFormatError) {
display("format error: {err}")
from()
source(err)
}
/// The Decoder does not support features required by the image. /// The Decoder does not support features required by the image.
UnsupportedError(TiffUnsupportedError), UnsupportedError(err: TiffUnsupportedError) {
display("unsupported error: {err}")
from()
source(err)
}
/// An I/O Error occurred while decoding the image. /// An I/O Error occurred while decoding the image.
IoError(io::Error), IoError(err: io::Error) {
display("{err}")
from()
source(err)
}
/// The Limits of the Decoder is exceeded. /// The Limits of the Decoder is exceeded.
LimitsExceeded, LimitsExceeded {
display("decoder limits exceeded")
/// An integer conversion to or from a platform size failed, either due to }
/// limits of the platform size or limits of the format. /// An integer conversion to or from a platform size failed.
IntSizeError, IntSizeError {
display("platform or format size limits exceeded")
}
/// The image does not support the requested operation /// The image does not support the requested operation
UsageError(UsageError), UsageError(err: UsageError) {
} display("usage error: {err}")
from()
/// The image is not formatted properly. source(err)
///
/// This indicates that the encoder producing the image might behave incorrectly or that the input
/// file has been corrupted.
///
/// The list of variants may grow to incorporate errors of future features. Matching against this
/// exhaustively is not covered by interface stability guarantees.
#[derive(Debug, Clone, PartialEq)]
#[non_exhaustive]
pub enum TiffFormatError {
TiffSignatureNotFound,
TiffSignatureInvalid,
ImageFileDirectoryNotFound,
InconsistentSizesEncountered,
UnexpectedCompressedData {
actual_bytes: usize,
required_bytes: usize,
},
InconsistentStripSamples {
actual_samples: usize,
required_samples: usize,
},
InvalidDimensions(u32, u32),
InvalidTag,
InvalidTagValueType(Tag),
RequiredTagNotFound(Tag),
UnknownPredictor(u16),
UnknownPlanarConfiguration(u16),
ByteExpected(Value),
SignedByteExpected(Value),
ShortExpected(Value),
SignedShortExpected(Value),
UnsignedIntegerExpected(Value),
SignedIntegerExpected(Value),
Format(String),
RequiredTagEmpty(Tag),
StripTileTagConflict,
CycleInOffsets,
JpegDecoder(JpegDecoderError),
SamplesPerPixelIsZero,
}
impl fmt::Display for TiffFormatError {
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
use self::TiffFormatError::*;
match *self {
TiffSignatureNotFound => write!(fmt, "TIFF signature not found."),
TiffSignatureInvalid => write!(fmt, "TIFF signature invalid."),
ImageFileDirectoryNotFound => write!(fmt, "Image file directory not found."),
InconsistentSizesEncountered => write!(fmt, "Inconsistent sizes encountered."),
UnexpectedCompressedData {
actual_bytes,
required_bytes,
} => {
write!(
fmt,
"Decompression returned different amount of bytes than expected: got {}, expected {}.",
actual_bytes, required_bytes
)
}
InconsistentStripSamples {
actual_samples,
required_samples,
} => {
write!(
fmt,
"Inconsistent elements in strip: got {}, expected {}.",
actual_samples, required_samples
)
}
InvalidDimensions(width, height) => write!(fmt, "Invalid dimensions: {}x{}.", width, height),
InvalidTag => write!(fmt, "Image contains invalid tag."),
InvalidTagValueType(ref tag) => {
write!(fmt, "Tag `{:?}` did not have the expected value type.", tag)
}
RequiredTagNotFound(ref tag) => write!(fmt, "Required tag `{:?}` not found.", tag),
UnknownPredictor(ref predictor) => {
write!(fmt, "Unknown predictor “{}” encountered", predictor)
}
UnknownPlanarConfiguration(ref planar_config) => {
write!(fmt, "Unknown planar configuration “{}” encountered", planar_config)
}
ByteExpected(ref val) => write!(fmt, "Expected byte, {:?} found.", val),
SignedByteExpected(ref val) => write!(fmt, "Expected signed byte, {:?} found.", val),
ShortExpected(ref val) => write!(fmt, "Expected short, {:?} found.", val),
SignedShortExpected(ref val) => write!(fmt, "Expected signed short, {:?} found.", val),
UnsignedIntegerExpected(ref val) => {
write!(fmt, "Expected unsigned integer, {:?} found.", val)
}
SignedIntegerExpected(ref val) => {
write!(fmt, "Expected signed integer, {:?} found.", val)
}
Format(ref val) => write!(fmt, "Invalid format: {:?}.", val),
RequiredTagEmpty(ref val) => write!(fmt, "Required tag {:?} was empty.", val),
StripTileTagConflict => write!(fmt, "File should contain either (StripByteCounts and StripOffsets) or (TileByteCounts and TileOffsets), other combination was found."),
CycleInOffsets => write!(fmt, "File contained a cycle in the list of IFDs"),
JpegDecoder(ref error) => write!(fmt, "{}", error),
SamplesPerPixelIsZero => write!(fmt, "Samples per pixel is zero"),
} }
} }
} }
/// The Decoder does not support features required by the image. quick_error! {
/// /// The image is not formatted properly.
/// This only captures known failures for which the standard either does not require support or an ///
/// implementation has been planned but not yet completed. Some variants may become unused over /// This indicates that the encoder producing the image might behave incorrectly or that the
/// time and will then get deprecated before being removed. /// input file has been corrupted.
/// #[derive(Debug, Clone, PartialEq)]
/// The list of variants may grow. Matching against this exhaustively is not covered by interface #[non_exhaustive]
/// stability guarantees. pub enum TiffFormatError {
#[derive(Debug, Clone, PartialEq, Eq, Hash)] TiffSignatureNotFound {
#[non_exhaustive] display("TIFF signature not found")
pub enum TiffUnsupportedError {
FloatingPointPredictor(ColorType),
HorizontalPredictor(ColorType),
InconsistentBitsPerSample(Vec<u8>),
InterpretationWithBits(PhotometricInterpretation, Vec<u8>),
UnknownInterpretation,
UnknownCompressionMethod,
UnsupportedCompressionMethod(CompressionMethod),
UnsupportedSampleDepth(u8),
UnsupportedSampleFormat(Vec<SampleFormat>),
UnsupportedColorType(ColorType),
UnsupportedBitsPerChannel(u8),
UnsupportedPlanarConfig(Option<PlanarConfiguration>),
UnsupportedDataType,
UnsupportedInterpretation(PhotometricInterpretation),
UnsupportedJpegFeature(UnsupportedFeature),
MisalignedTileBoundaries,
}
impl fmt::Display for TiffUnsupportedError {
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
use self::TiffUnsupportedError::*;
match *self {
FloatingPointPredictor(color_type) => write!(
fmt,
"Floating point predictor for {:?} is unsupported.",
color_type
),
HorizontalPredictor(color_type) => write!(
fmt,
"Horizontal predictor for {:?} is unsupported.",
color_type
),
InconsistentBitsPerSample(ref bits_per_sample) => {
write!(fmt, "Inconsistent bits per sample: {:?}.", bits_per_sample)
} }
InterpretationWithBits(ref photometric_interpretation, ref bits_per_sample) => write!( TiffSignatureInvalid {
fmt, display("TIFF signature invalid")
"{:?} with {:?} bits per sample is unsupported",
photometric_interpretation, bits_per_sample
),
UnknownInterpretation => write!(
fmt,
"The image is using an unknown photometric interpretation."
),
UnknownCompressionMethod => write!(fmt, "Unknown compression method."),
UnsupportedCompressionMethod(method) => {
write!(fmt, "Compression method {:?} is unsupported", method)
} }
UnsupportedSampleDepth(samples) => { ImageFileDirectoryNotFound {
write!(fmt, "{} samples per pixel is unsupported.", samples) display("image file directory not found")
} }
UnsupportedSampleFormat(ref formats) => { InconsistentSizesEncountered {
write!(fmt, "Sample format {:?} is unsupported.", formats) display("inconsistent sizes encountered")
} }
UnsupportedColorType(color_type) => { InvalidDimensions(width: u32, height: u32) {
write!(fmt, "Color type {:?} is unsupported", color_type) display("invalid dimensions: {width}x{height}")
} }
UnsupportedBitsPerChannel(bits) => { InvalidTag {
write!(fmt, "{} bits per channel not supported", bits) display("image contains invalid tag")
} }
UnsupportedPlanarConfig(config) => { InvalidTagValueType(tag: Tag) {
write!(fmt, "Unsupported planar configuration “{:?}”.", config) display("tag `{tag:?}` did not have the expected value type")
} }
UnsupportedDataType => write!(fmt, "Unsupported data type."), RequiredTagNotFound(tag: Tag) {
UnsupportedInterpretation(interpretation) => { display("required tag `{tag:?}` not found")
write!(
fmt,
"Unsupported photometric interpretation \"{:?}\".",
interpretation
)
} }
UnsupportedJpegFeature(ref unsupported_feature) => { UnknownPredictor(pred: u16) {
write!(fmt, "Unsupported JPEG feature {:?}", unsupported_feature) display("unknown predictor “{pred}” encountered")
} }
MisalignedTileBoundaries => write!(fmt, "Tile rows are not aligned to byte boundaries"), UnknownPlanarConfiguration(cfg: u16) {
display("unknown planar configuration “{cfg}”")
}
InvalidTypeForTag {
display("tag has invalid type")
}
StripTileTagConflict {
display("file should contain either (StripByteCounts and StripOffsets) or (TileByteCounts and TileOffsets), other combination was found")
}
CycleInOffsets {
display("file contained a cycle in the list of IFDs")
}
SamplesPerPixelIsZero {
display("samples per pixel is zero")
}
CompressedDataCorrupt(message: String) {
display("compressed data is corrupt: {message}")
} }
} }
} }
/// User attempted to use the Decoder in a way that is incompatible with a specific image. quick_error! {
/// /// The Decoder does not support features required by the image.
/// For example: attempting to read a tile from a stripped image. ///
#[derive(Debug)] /// This only captures known failures for which the standard either does not require support or an
pub enum UsageError { /// implementation has been planned but not yet completed. Some variants may become unused over
InvalidChunkType(ChunkType, ChunkType), /// time and will then get deprecated before being removed.
InvalidChunkIndex(u32), #[derive(Debug, Clone, PartialEq, Eq, Hash)]
PredictorCompressionMismatch, #[non_exhaustive]
PredictorIncompatible, pub enum TiffUnsupportedError {
PredictorUnavailable, FloatingPointPredictor(color_type: ColorType) {
} display("floating point predictor for {color_type:?} is unsupported")
impl fmt::Display for UsageError {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
use self::UsageError::*;
match *self {
InvalidChunkType(expected, actual) => {
write!(
fmt,
"Requested operation is only valid for images with chunk encoding of type: {:?}, got {:?}.",
expected, actual
)
} }
InvalidChunkIndex(index) => write!(fmt, "Image chunk index ({}) requested.", index), HorizontalPredictor(color_type: ColorType) {
PredictorCompressionMismatch => write!( display("horizontal predictor for {color_type:?} is unsupported")
fmt, }
"The requested predictor is not compatible with the requested compression" InconsistentBitsPerSample(bits_per_sample: Vec<u8>) {
), display("inconsistent bits per sample: {bits_per_sample:?}")
PredictorIncompatible => write!( }
fmt, InterpretationWithBits(interpretation: PhotometricInterpretation, bits_per_sample: Vec<u8>) {
"The requested predictor is not compatible with the image's format" display("Photometric interpretation {interpretation:?} with bits per sample {bits_per_sample:?} is unsupported")
), }
PredictorUnavailable => write!(fmt, "The requested predictor is not available"), UnknownInterpretation {
display("unknown photometric interpretation")
}
UnknownCompressionMethod {
display("unknown compression method")
}
UnsupportedCompressionMethod(method: CompressionMethod) {
display("compression method {method:?} is unsupported")
}
UnsupportedSampleDepth(depth: u8) {
display("{depth} samples per pixel is unsupported")
}
UnsupportedSampleFormat(sample_format: Vec<SampleFormat>) {
display("sample format {sample_format:?} is unsupported")
}
UnsupportedColorType(color_type: ColorType) {
display("color type {color_type:?} is unsupported")
}
UnsupportedBitsPerChannel(bits_per_channel: u8) {
display("{bits_per_channel} bits per channel not supported")
}
UnsupportedPlanarConfig(planar: Option<PlanarConfiguration>) {
display("unsupported planar configuration “{planar:?}”")
}
UnsupportedDataType {
display("unsupported data type.")
}
UnsupportedInterpretation(interpretation: PhotometricInterpretation) {
display("unsupported photometric interpretation \"{interpretation:?}\"")
}
UnsupportedJpegFeature(feature: UnsupportedFeature) {
display("unsupported JPEG feature {feature:?}")
}
MisalignedTileBoundaries {
display("tile rows are not aligned to byte boundaries")
} }
} }
} }
impl fmt::Display for TiffError { quick_error! {
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { /// User attempted to use the Decoder in a way that is incompatible with a specific image.
match *self { ///
TiffError::FormatError(ref e) => write!(fmt, "Format error: {}", e), /// For example: attempting to read a tile from a stripped image.
TiffError::UnsupportedError(ref f) => write!( #[derive(Debug)]
fmt, #[non_exhaustive]
"The Decoder does not support the \ pub enum UsageError {
image format `{}`", InvalidChunkType(expected: ChunkType, actual: ChunkType) {
f display("requested operation is only valid for images with chunk encoding of type {expected:?} but got {actual:?}")
),
TiffError::IoError(ref e) => e.fmt(fmt),
TiffError::LimitsExceeded => write!(fmt, "The Decoder limits are exceeded"),
TiffError::IntSizeError => write!(fmt, "Platform or format size limits exceeded"),
TiffError::UsageError(ref e) => write!(fmt, "Usage error: {}", e),
} }
InvalidChunkIndex(index: u32) {
display("invalid chunk index ({index}) requested")
} }
} PredictorCompressionMismatch {
display("requested predictor is not compatible with the requested compression")
impl Error for TiffError {
fn description(&self) -> &str {
match *self {
TiffError::FormatError(..) => "Format error",
TiffError::UnsupportedError(..) => "Unsupported error",
TiffError::IoError(..) => "IO error",
TiffError::LimitsExceeded => "Decoder limits exceeded",
TiffError::IntSizeError => "Platform or format size limits exceeded",
TiffError::UsageError(..) => "Invalid usage",
} }
PredictorIncompatible {
display("the requested predictor is not compatible with the image's format")
} }
PredictorUnavailable {
fn cause(&self) -> Option<&dyn Error> { display("the requested predictor is not available")
match *self {
TiffError::IoError(ref e) => Some(e),
_ => None,
} }
} }
} }
impl From<io::Error> for TiffError {
fn from(err: io::Error) -> TiffError {
TiffError::IoError(err)
}
}
impl From<str::Utf8Error> for TiffError { impl From<str::Utf8Error> for TiffError {
fn from(_err: str::Utf8Error) -> TiffError { fn from(_err: str::Utf8Error) -> TiffError {
TiffError::FormatError(TiffFormatError::InvalidTag) TiffError::FormatError(TiffFormatError::InvalidTag)
@@ -324,24 +205,6 @@ impl From<string::FromUtf8Error> for TiffError {
} }
} }
impl From<TiffFormatError> for TiffError {
fn from(err: TiffFormatError) -> TiffError {
TiffError::FormatError(err)
}
}
impl From<TiffUnsupportedError> for TiffError {
fn from(err: TiffUnsupportedError) -> TiffError {
TiffError::UnsupportedError(err)
}
}
impl From<UsageError> for TiffError {
fn from(err: UsageError) -> TiffError {
TiffError::UsageError(err)
}
}
impl From<std::num::TryFromIntError> for TiffError { impl From<std::num::TryFromIntError> for TiffError {
fn from(_err: std::num::TryFromIntError) -> TiffError { fn from(_err: std::num::TryFromIntError) -> TiffError {
TiffError::IntSizeError TiffError::IntSizeError
@@ -350,48 +213,13 @@ impl From<std::num::TryFromIntError> for TiffError {
impl From<LzwError> for TiffError { impl From<LzwError> for TiffError {
fn from(err: LzwError) -> TiffError { fn from(err: LzwError) -> TiffError {
match err { TiffError::FormatError(TiffFormatError::CompressedDataCorrupt(err.to_string()))
LzwError::InvalidCode => TiffError::FormatError(TiffFormatError::Format(String::from(
"LZW compressed data corrupted",
))),
}
}
}
#[derive(Debug, Clone)]
pub struct JpegDecoderError {
inner: Arc<jpeg::Error>,
}
impl JpegDecoderError {
fn new(error: jpeg::Error) -> Self {
Self {
inner: Arc::new(error),
}
}
}
impl PartialEq for JpegDecoderError {
fn eq(&self, other: &Self) -> bool {
Arc::ptr_eq(&self.inner, &other.inner)
}
}
impl Display for JpegDecoderError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.inner.fmt(f)
}
}
impl From<JpegDecoderError> for TiffError {
fn from(error: JpegDecoderError) -> Self {
TiffError::FormatError(TiffFormatError::JpegDecoder(error))
} }
} }
impl From<jpeg::Error> for TiffError { impl From<jpeg::Error> for TiffError {
fn from(error: jpeg::Error) -> Self { fn from(err: jpeg::Error) -> Self {
JpegDecoderError::new(error).into() TiffError::FormatError(TiffFormatError::CompressedDataCorrupt(err.to_string()))
} }
} }