#[cfg(feature = "ciborium")]
use core::convert::Infallible;
use core::fmt;
use crate::alloc::String;
#[cfg(feature = "ciborium")]
pub(crate) type CborDeError<E = anyhow::Error> = ciborium::de::Error<E>;
#[cfg(feature = "ciborium")]
pub(crate) type CborSerError<E = Infallible> = ciborium::ser::Error<E>;
#[derive(Debug)]
#[non_exhaustive]
pub enum ParseError {
    InvalidTokenStructure,
    InvalidBase64Encoding,
    MalformedHeader(serde_json::Error),
    UnsupportedContentType(String),
}
impl fmt::Display for ParseError {
    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Self::InvalidTokenStructure => formatter.write_str("invalid token structure"),
            Self::InvalidBase64Encoding => write!(formatter, "invalid base64 decoding"),
            Self::MalformedHeader(err) => write!(formatter, "malformed token header: {err}"),
            Self::UnsupportedContentType(ty) => {
                write!(formatter, "unsupported content type: {ty}")
            }
        }
    }
}
#[cfg(feature = "std")]
impl std::error::Error for ParseError {
    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        match self {
            Self::MalformedHeader(err) => Some(err),
            _ => None,
        }
    }
}
#[derive(Debug)]
#[non_exhaustive]
pub enum ValidationError {
    AlgorithmMismatch {
        expected: String,
        actual: String,
    },
    InvalidSignatureLen {
        expected: usize,
        actual: usize,
    },
    MalformedSignature(anyhow::Error),
    InvalidSignature,
    MalformedClaims(serde_json::Error),
    #[cfg(feature = "ciborium")]
    #[cfg_attr(docsrs, doc(cfg(feature = "ciborium")))]
    MalformedCborClaims(CborDeError),
    NoClaim(Claim),
    Expired,
    NotMature,
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum Claim {
    Expiration,
    NotBefore,
}
impl fmt::Display for Claim {
    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
        formatter.write_str(match self {
            Self::Expiration => "exp",
            Self::NotBefore => "nbf",
        })
    }
}
impl fmt::Display for ValidationError {
    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Self::AlgorithmMismatch { expected, actual } => write!(
                formatter,
                "token algorithm ({actual}) differs from expected ({expected})"
            ),
            Self::InvalidSignatureLen { expected, actual } => write!(
                formatter,
                "invalid signature length: expected {expected} bytes, got {actual} bytes"
            ),
            Self::MalformedSignature(err) => write!(formatter, "malformed token signature: {err}"),
            Self::InvalidSignature => formatter.write_str("signature has failed verification"),
            Self::MalformedClaims(err) => write!(formatter, "cannot deserialize claims: {err}"),
            #[cfg(feature = "ciborium")]
            Self::MalformedCborClaims(err) => write!(formatter, "cannot deserialize claims: {err}"),
            Self::NoClaim(claim) => write!(
                formatter,
                "claim `{claim}` requested during validation is not present in the token"
            ),
            Self::Expired => formatter.write_str("token has expired"),
            Self::NotMature => formatter.write_str("token is not yet ready"),
        }
    }
}
#[cfg(feature = "std")]
impl std::error::Error for ValidationError {
    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        match self {
            Self::MalformedSignature(err) => Some(err.as_ref()),
            Self::MalformedClaims(err) => Some(err),
            #[cfg(feature = "ciborium")]
            Self::MalformedCborClaims(err) => Some(err),
            _ => None,
        }
    }
}
#[derive(Debug)]
#[non_exhaustive]
pub enum CreationError {
    Header(serde_json::Error),
    Claims(serde_json::Error),
    #[cfg(feature = "ciborium")]
    #[cfg_attr(docsrs, doc(cfg(feature = "ciborium")))]
    CborClaims(CborSerError),
}
impl fmt::Display for CreationError {
    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Self::Header(err) => write!(formatter, "cannot serialize header: {err}"),
            Self::Claims(err) => write!(formatter, "cannot serialize claims: {err}"),
            #[cfg(feature = "ciborium")]
            Self::CborClaims(err) => write!(formatter, "cannot serialize claims into CBOR: {err}"),
        }
    }
}
#[cfg(feature = "std")]
impl std::error::Error for CreationError {
    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        match self {
            Self::Header(err) | Self::Claims(err) => Some(err),
            #[cfg(feature = "ciborium")]
            Self::CborClaims(err) => Some(err),
        }
    }
}