use thiserror::Error;
use super::{
capacity_error::CapacityError,
transcode_decode_error::TranscodeDecodeError,
transcode_domain_error::TranscodeDomainError,
transcode_encode_error::TranscodeEncodeError,
transcode_failure::TranscodeFailure,
};
use crate::Codec;
pub type TranscodeConvertErrorOf<D, E> = TranscodeConvertError<
<D as Codec>::DecodeError,
<E as Codec>::EncodeError,
<D as Codec>::Value,
>;
#[derive(Clone, Debug, Eq, Error, Hash, PartialEq)]
pub enum TranscodeConvertError<DE, EE, V> {
#[error(transparent)]
Failure(#[from] TranscodeFailure),
#[error("decode side failed: {0}")]
DecodeDomain(#[source] TranscodeDomainError<DE>),
#[error("encode side failed: {0}")]
EncodeDomain(#[source] TranscodeDomainError<EE>),
#[error("unencodable value at input index {input_index}")]
Unencodable {
input_index: usize,
value: Option<V>,
},
}
impl<DE, EE, V> TranscodeConvertError<DE, EE, V> {
#[inline(always)]
pub const fn decode_domain_reset(source: DE) -> Self {
Self::DecodeDomain(TranscodeDomainError::reset(source))
}
#[inline(always)]
pub const fn decode_domain_main(source: DE, input_index: usize) -> Self {
Self::DecodeDomain(TranscodeDomainError::main(source, input_index))
}
#[inline(always)]
pub const fn decode_domain_main_with_consumed(
source: DE,
input_index: usize,
input_consumed: Option<core::num::NonZeroUsize>,
) -> Self {
Self::DecodeDomain(TranscodeDomainError::main_with_consumed(
source,
input_index,
input_consumed,
))
}
#[inline(always)]
pub const fn decode_domain_finish(source: DE) -> Self {
Self::DecodeDomain(TranscodeDomainError::finish(source))
}
#[inline(always)]
pub const fn encode_domain_reset(source: EE) -> Self {
Self::EncodeDomain(TranscodeDomainError::reset(source))
}
#[inline(always)]
pub const fn encode_domain_main(source: EE, input_index: usize) -> Self {
Self::EncodeDomain(TranscodeDomainError::main(source, input_index))
}
#[inline(always)]
pub const fn encode_domain_finish(source: EE) -> Self {
Self::EncodeDomain(TranscodeDomainError::finish(source))
}
#[inline(always)]
#[must_use]
pub fn unencodable(input_index: usize, value: V) -> Self {
Self::Unencodable {
input_index,
value: Some(value),
}
}
#[inline(always)]
#[must_use]
pub const fn unencodable_without_context(input_index: usize) -> Self {
Self::Unencodable {
input_index,
value: None,
}
}
#[inline(always)]
#[must_use]
pub const fn failure_ref(&self) -> Option<&TranscodeFailure> {
match self {
Self::Failure(failure) => Some(failure),
Self::DecodeDomain(_)
| Self::EncodeDomain(_)
| Self::Unencodable { .. } => None,
}
}
#[inline(always)]
#[must_use]
pub const fn unencodable_ref(&self) -> Option<(usize, Option<&V>)> {
match self {
Self::Unencodable { input_index, value } => {
Some((*input_index, value.as_ref()))
}
Self::Failure(_)
| Self::DecodeDomain(_)
| Self::EncodeDomain(_) => None,
}
}
#[inline]
pub fn map_decode_domain<F, T>(
self,
f: F,
) -> TranscodeConvertError<T, EE, V>
where
F: FnOnce(DE) -> T,
{
match self {
Self::Failure(failure) => TranscodeConvertError::Failure(failure),
Self::DecodeDomain(error) => {
TranscodeConvertError::DecodeDomain(error.map_source(f))
}
Self::EncodeDomain(error) => {
TranscodeConvertError::EncodeDomain(error)
}
Self::Unencodable { input_index, value } => {
TranscodeConvertError::Unencodable { input_index, value }
}
}
}
#[inline]
pub fn map_encode_domain<F, T>(
self,
f: F,
) -> TranscodeConvertError<DE, T, V>
where
F: FnOnce(EE) -> T,
{
match self {
Self::Failure(failure) => TranscodeConvertError::Failure(failure),
Self::DecodeDomain(error) => {
TranscodeConvertError::DecodeDomain(error)
}
Self::EncodeDomain(error) => {
TranscodeConvertError::EncodeDomain(error.map_source(f))
}
Self::Unencodable { input_index, value } => {
TranscodeConvertError::Unencodable { input_index, value }
}
}
}
#[inline]
pub fn map_value<F, W>(self, f: F) -> TranscodeConvertError<DE, EE, W>
where
F: FnOnce(V) -> W,
{
match self {
Self::Failure(failure) => TranscodeConvertError::Failure(failure),
Self::DecodeDomain(error) => {
TranscodeConvertError::DecodeDomain(error)
}
Self::EncodeDomain(error) => {
TranscodeConvertError::EncodeDomain(error)
}
Self::Unencodable { input_index, value } => {
TranscodeConvertError::Unencodable {
input_index,
value: value.map(f),
}
}
}
}
#[inline]
pub fn from_encode_error_with_value(
error: TranscodeEncodeError<EE, V>,
fallback_value: V,
) -> Self {
match error {
TranscodeEncodeError::Unencodable {
input_index,
value: None,
} => Self::Unencodable {
input_index,
value: Some(fallback_value),
},
other => Self::from(other),
}
}
}
impl<DE, EE, V> From<TranscodeDecodeError<DE>>
for TranscodeConvertError<DE, EE, V>
{
#[inline]
fn from(error: TranscodeDecodeError<DE>) -> Self {
match error {
TranscodeDecodeError::Failure(failure) => Self::Failure(failure),
TranscodeDecodeError::Domain(error) => Self::DecodeDomain(error),
}
}
}
impl<DE, EE, V> From<TranscodeEncodeError<EE, V>>
for TranscodeConvertError<DE, EE, V>
{
#[inline]
fn from(error: TranscodeEncodeError<EE, V>) -> Self {
match error {
TranscodeEncodeError::Failure(failure) => Self::Failure(failure),
TranscodeEncodeError::Unencodable { input_index, value } => {
Self::Unencodable { input_index, value }
}
TranscodeEncodeError::Domain(error) => Self::EncodeDomain(error),
}
}
}
impl<DE, EE, V> From<CapacityError> for TranscodeConvertError<DE, EE, V> {
#[inline(always)]
fn from(error: CapacityError) -> Self {
TranscodeFailure::from(error).into()
}
}