use std::fmt::{self, Display};
use std::future::Future;
use std::pin::Pin;
use std::time::Duration;
use crate::Image;
pub type ImageCodecFuture =
Pin<Box<dyn Future<Output = Result<Box<dyn ImageCodec>, ImageDecodeError>>>>;
pub type ImageFrameFuture<'a> =
Pin<Box<dyn Future<Output = Result<ImageFrame, ImageDecodeError>> + 'a>>;
pub trait ImageCodec {
fn frame_count(&self) -> u32;
fn repetition(&self) -> ImageRepetition;
fn next_frame(&mut self) -> ImageFrameFuture<'_>;
}
#[derive(Clone, Debug)]
pub struct ImageFrame {
pub image: Image,
pub duration: Duration,
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub enum ImageRepetition {
#[default]
Once,
Times(u32),
Forever,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum ImageDecodeError {
NoDecoder,
UnknownFormat,
Damaged(String),
Empty,
Failed(String),
}
impl Display for ImageDecodeError {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ImageDecodeError::NoDecoder => formatter.write_str("this host decodes no images"),
ImageDecodeError::UnknownFormat => formatter.write_str("unrecognised image format"),
ImageDecodeError::Damaged(reason) => write!(formatter, "damaged image: {reason}"),
ImageDecodeError::Empty => formatter.write_str("image has no pixels"),
ImageDecodeError::Failed(reason) => write!(formatter, "image decode failed: {reason}"),
}
}
}
impl std::error::Error for ImageDecodeError {}