use std::error::Error;
use std::fmt::{Debug, Display, Formatter};
use crate::decoder::MAX_DIMENSIONS;
use crate::misc::{
START_OF_FRAME_EXT_AR, START_OF_FRAME_EXT_SEQ, START_OF_FRAME_LOS_SEQ,
START_OF_FRAME_LOS_SEQ_AR, START_OF_FRAME_PROG_DCT_AR,
};
#[allow(clippy::module_name_repetitions)]
pub enum DecodeErrors
{
Format(String),
FormatStatic(&'static str),
IllegalMagicBytes(u16),
HuffmanDecode(String),
ZeroError,
DqtError(String),
SosError(String),
SofError(String),
Unsupported(UnsupportedSchemes),
MCUError(String),
ExhaustedData,
LargeDimensions(usize),
}
impl Debug for DecodeErrors
{
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result
{
match &self
{
Self::Format(ref a) => write!(f, "{:?}", a),
Self::FormatStatic(ref a) => write!(f, "{:?}", a),
Self::HuffmanDecode(ref reason) =>
{
write!(f, "Error decoding huffman values: {}", reason)
}
Self::ZeroError => write!(f, "Image width or height is set to zero, cannot continue"),
Self::DqtError(ref reason) => write!(f, "Error parsing DQT segment. Reason:{}", reason),
Self::SosError(ref reason) => write!(f, "Error parsing SOS Segment. Reason:{}", reason),
Self::SofError(ref reason) => write!(f, "Error parsing SOF segment. Reason:{}", reason),
Self::IllegalMagicBytes(bytes) =>
{
write!(f, "Error parsing image. Illegal start bytes:{}", bytes)
}
Self::MCUError(ref reason) => write!(f, "Error in decoding MCU. Reason {}", reason),
Self::Unsupported(ref image_type) =>
{
write!(f, "{:?}", image_type)
}
Self::ExhaustedData => write!(f, "Exhausted data in the image"),
Self::LargeDimensions(ref dimensions) => write!(
f,
"Too large dimensions {},library supports up to {}",
dimensions, MAX_DIMENSIONS
),
}
}
}
impl Display for DecodeErrors
{
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result
{
match &self
{
Self::Format(ref a) => write!(f, "{}", a),
Self::FormatStatic(ref a) => write!(f, "{:?}", a),
Self::HuffmanDecode(ref reason) =>
{
write!(f, "Error decoding huffman tables.Reason:{}", reason)
}
Self::ZeroError => write!(f, "Image width or height is set to zero, cannot continue"),
Self::DqtError(ref reason) => write!(f, "Error parsing DQT segment. Reason:{}", reason),
Self::SosError(ref reason) => write!(f, "Error parsing SOS Segment. Reason:{}", reason),
Self::SofError(ref reason) => write!(f, "Error parsing SOF segment. Reason:{}", reason),
Self::IllegalMagicBytes(bytes) =>
{
write!(f, "Error parsing image. Illegal start bytes:{}", bytes)
}
Self::Unsupported(ref image_type) =>
{
write!(f, "{:?}", image_type)
}
Self::MCUError(ref reason) => write!(f, "Error in decoding MCU. Reason {}", reason),
Self::ExhaustedData => write!(f, "Exhausted data in the image"),
Self::LargeDimensions(ref dimensions) => write!(
f,
"Too large dimensions {},library supports up to {}",
dimensions, MAX_DIMENSIONS
),
}
}
}
impl Error for DecodeErrors {}
impl From<Box<dyn Error>> for DecodeErrors
{
fn from(err: Box<dyn Error>) -> Self
{
DecodeErrors::Format(format!("Error decoding an image:\n {}", err))
}
}
impl From<std::io::Error> for DecodeErrors
{
fn from(err: std::io::Error) -> Self
{
DecodeErrors::Format(format!("Error decoding an image:\n {}", err))
}
}
#[derive(Eq, PartialEq, Copy, Clone)]
pub enum UnsupportedSchemes
{
ExtendedSequentialHuffman,
LosslessHuffman,
ExtendedSequentialDctArithmetic,
ProgressiveDctArithmetic,
LosslessArithmetic,
}
impl Debug for UnsupportedSchemes
{
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result
{
match &self
{
Self::ExtendedSequentialHuffman =>
{
write!(f,"The library cannot yet decode images encoded using Extended Sequential Huffman encoding scheme yet.")
}
Self::LosslessHuffman =>
{
write!(f,"The library cannot yet decode images encoded with Lossless Huffman encoding scheme")
}
Self::ExtendedSequentialDctArithmetic =>
{
write!(f,"The library cannot yet decode Images Encoded with Extended Sequential DCT Arithmetic scheme")
}
Self::ProgressiveDctArithmetic =>
{
write!(f,"The library cannot yet decode images encoded with Progressive DCT Arithmetic scheme")
}
Self::LosslessArithmetic =>
{
write!(f,"The library cannot yet decode images encoded with Lossless Arithmetic encoding scheme")
}
}
}
}
impl UnsupportedSchemes
{
#[must_use]
pub fn from_int(int: u8) -> Option<UnsupportedSchemes>
{
let int = u16::from_be_bytes([0xff, int]);
match int
{
START_OF_FRAME_PROG_DCT_AR => Some(Self::ProgressiveDctArithmetic),
START_OF_FRAME_LOS_SEQ => Some(Self::LosslessHuffman),
START_OF_FRAME_LOS_SEQ_AR => Some(Self::LosslessArithmetic),
START_OF_FRAME_EXT_SEQ => Some(Self::ExtendedSequentialHuffman),
START_OF_FRAME_EXT_AR => Some(Self::ExtendedSequentialDctArithmetic),
_ => None,
}
}
}