use crate::prelude::*;
use crate::ProduceAtLeastError;
use core::{
convert::Infallible,
fmt::{Debug, Display, Formatter},
};
use core::error::Error;
pub trait Decodable<Symbol = u8>: Sized {
type ErrorReason;
async fn decode<P>(
producer: &mut P,
) -> Result<Self, DecodeError<P::Final, P::Error, Self::ErrorReason>>
where
P: BulkProducer<Item = Symbol> + ?Sized,
Self: Sized;
}
pub trait DecodableCanonic<Symbol = u8>: Decodable<Symbol> {
type ErrorCanonic: From<Self::ErrorReason>;
async fn decode_canonic<P>(
producer: &mut P,
) -> Result<Self, DecodeError<P::Final, P::Error, Self::ErrorCanonic>>
where
P: BulkProducer<Item = Symbol> + ?Sized,
Self: Sized;
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum DecodeError<F, E, Other> {
UnexpectedEndOfInput(F),
ProducerError(E),
Other(Other),
}
impl<F, E, Other> DecodeError<F, E, Other> {
pub fn map_other<OtherB, Fun>(self, fun: Fun) -> DecodeError<F, E, OtherB>
where
Fun: FnOnce(Other) -> OtherB,
{
match self {
DecodeError::Other(other) => DecodeError::Other(fun(other)),
DecodeError::UnexpectedEndOfInput(fin) => DecodeError::UnexpectedEndOfInput(fin),
DecodeError::ProducerError(err) => DecodeError::ProducerError(err),
}
}
}
impl<F, E, Other> From<E> for DecodeError<F, E, Other> {
fn from(err: E) -> Self {
DecodeError::ProducerError(err)
}
}
impl<F, E, Other> From<ProduceAtLeastError<F, E>> for DecodeError<F, E, Other> {
fn from(err: ProduceAtLeastError<F, E>) -> Self {
match err.reason {
Ok(fin) => DecodeError::UnexpectedEndOfInput(fin),
Err(err) => DecodeError::ProducerError(err),
}
}
}
impl<F: Display, E: Display, Other: Display> Display for DecodeError<F, E, Other> {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
match self {
DecodeError::ProducerError(err) => {
write!(f, "Failed to decode a value because the producer of code symbols encountered an error: {err}",)
}
DecodeError::UnexpectedEndOfInput(fin) => {
write!(
f,
"Failed to decode a value because the producer of code symbols emitted its final value unexpectedly early: {fin}"
)
}
DecodeError::Other(reason) => {
write!(f, "Failed to decode a value: {reason}")
}
}
}
}
impl<F, E, Other> Error for DecodeError<F, E, Other>
where
F: Display + Debug,
E: 'static + Error,
Other: 'static + Error,
{
fn source(&self) -> Option<&(dyn Error + 'static)> {
match self {
DecodeError::ProducerError(err) => Some(err),
DecodeError::UnexpectedEndOfInput(_fin) => None,
DecodeError::Other(reason) => Some(reason),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum Blame {
TheirFault,
OurFault,
}
impl Blame {
pub fn u64_to_usize<F, E>(n: u64) -> Result<usize, DecodeError<F, E, Blame>> {
usize::try_from(n).map_err(|_| DecodeError::Other(Blame::OurFault))
}
pub fn u32_to_usize<F, E>(n: u32) -> Result<usize, DecodeError<F, E, Blame>> {
usize::try_from(n).map_err(|_| DecodeError::Other(Blame::OurFault))
}
pub fn i64_to_usize<F, E>(n: i64) -> Result<isize, DecodeError<F, E, Blame>> {
isize::try_from(n).map_err(|_| DecodeError::Other(Blame::OurFault))
}
pub fn i32_to_usize<F, E>(n: i32) -> Result<isize, DecodeError<F, E, Blame>> {
isize::try_from(n).map_err(|_| DecodeError::Other(Blame::OurFault))
}
}
impl From<Infallible> for Blame {
fn from(_value: Infallible) -> Self {
unreachable!()
}
}
impl Display for Blame {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
match self {
Blame::TheirFault => {
write!(f, "Received an incorrect encoding.")
}
Blame::OurFault => {
write!(
f,
"Received a correct encoding which we could not process for some reason."
)
}
}
}
}
impl Error for Blame {}