use core::fmt;
use std::error::Error;
use crate::{
Charset,
CharsetDecodeErrorKind,
};
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct CharsetDecodeError {
charset: Charset,
kind: CharsetDecodeErrorKind,
index: usize,
consumed: usize,
}
pub type CharsetDecodeResult<T> = Result<T, CharsetDecodeError>;
impl CharsetDecodeError {
#[inline(always)]
pub const fn new(
charset: Charset,
kind: CharsetDecodeErrorKind,
index: usize,
) -> Self {
Self {
charset,
kind,
index,
consumed: 1,
}
}
#[must_use]
#[inline(always)]
pub const fn with_consumed(self, consumed: usize) -> Self {
Self {
charset: self.charset,
kind: self.kind,
index: self.index,
consumed,
}
}
#[inline(always)]
pub const fn charset(self) -> Charset {
self.charset
}
#[inline(always)]
pub const fn kind(self) -> CharsetDecodeErrorKind {
self.kind
}
#[inline(always)]
pub const fn index(self) -> usize {
self.index
}
#[inline(always)]
pub const fn required(self) -> Option<usize> {
self.kind.required()
}
#[inline(always)]
pub const fn available(self) -> Option<usize> {
self.kind.available()
}
#[inline(always)]
pub const fn input_len(self) -> Option<usize> {
self.kind.input_len()
}
#[inline(always)]
pub const fn output_len(self) -> Option<usize> {
self.kind.output_len()
}
#[inline(always)]
pub const fn value(self) -> Option<u32> {
self.kind.value()
}
#[inline(always)]
pub const fn consumed(self) -> Option<usize> {
match self.kind {
CharsetDecodeErrorKind::MalformedSequence { .. }
| CharsetDecodeErrorKind::InvalidCodePoint { .. } => {
Some(self.consumed)
}
CharsetDecodeErrorKind::IncompleteSequence { .. }
| CharsetDecodeErrorKind::InvalidInputIndex { .. }
| CharsetDecodeErrorKind::InvalidOutputIndex { .. } => None,
}
}
#[inline(always)]
pub const fn offset_by(self, base: usize) -> Self {
Self {
charset: self.charset,
kind: self.kind,
index: match self.index.checked_add(base) {
Some(index) => index,
None => usize::MAX,
},
consumed: self.consumed,
}
}
}
impl fmt::Display for CharsetDecodeError {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
if let Some(value) = self.kind.value() {
write!(
formatter,
"{} decoding error at index {} for value 0x{:x}: {}",
self.charset, self.index, value, self.kind,
)
} else {
write!(
formatter,
"{} decoding error at index {}: {}",
self.charset, self.index, self.kind,
)
}
}
}
impl Error for CharsetDecodeError {}