fakejpeg 0.2.0

Rust port of Alun Jones' fakejpeg library
Documentation
// SPDX-FileCopyrightText: Gergely Nagy
// SPDX-FileContributor: Gergely Nagy
//
// SPDX-License-Identifier: MIT

use std::{
    error::Error as StdError,
    fmt::{self, Display},
};
use winnow::error::ContextError;

/// Blah
///
/// It implements [`Error`] and [`Display`], the two methods whith which to
/// consume it.
#[derive(Debug)]
pub enum Error {
    /// A parse error.
    ///
    /// It holds information about where the error happened, and some context.
    ParseError(Context),
    /// The template is empty.
    EmptyTemplate,
}

/// A [`Result`](std::result::Result) with its error component set to [`Error`].
pub type Result<T> = std::result::Result<T, Error>;

impl Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Self::ParseError(error) => {
                write!(f, "parsing stopped at byte offset `{}`", error.offset)?;
                if error.inner.context().next().is_some() {
                    write!(f, " ({})", error.inner)?;
                }
            }
            Self::EmptyTemplate => {
                write!(f, "Template is empty")?;
            }
        }
        Ok(())
    }
}

impl Error {
    pub(crate) fn parse_error(offset: usize, inner: ContextError) -> Self {
        Self::ParseError(Context { offset, inner })
    }
}

impl StdError for Error {
    fn source(&self) -> Option<&(dyn StdError + 'static)> {
        match self {
            Self::ParseError(error) => error.inner.cause().map(|v| v as &(dyn StdError + 'static)),
            Self::EmptyTemplate => None,
        }
    }
}

#[derive(Debug)]
pub struct Context {
    pub(crate) offset: usize,
    pub(crate) inner: ContextError,
}