use rama_core::error::BoxError;
use super::common::ReadError;
use std::{fmt, str::Utf8Error};
#[derive(Debug)]
pub enum ProtocolError {
IO(std::io::Error),
UnexpectedByte { pos: usize, byte: u8 },
Unexpected(BoxError),
Utf8(Utf8Error),
}
impl ProtocolError {
#[must_use]
pub fn unexpected_byte(pos: usize, byte: u8) -> Self {
Self::UnexpectedByte { pos, byte }
}
}
impl fmt::Display for ProtocolError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::IO(error) => write!(f, "protocol error: I/O: {error}"),
Self::UnexpectedByte { pos, byte } => {
write!(
f,
"protocol error: unexpected byte x'{byte:x}' at position {pos}"
)
}
Self::Unexpected(error) => {
write!(f, "protocol error: unexpected: {error}")
}
Self::Utf8(error) => {
write!(f, "protocol error: utf-8 conversion: {error}")
}
}
}
}
impl std::error::Error for ProtocolError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Self::IO(err) => Some(err as &(dyn std::error::Error + 'static)),
Self::UnexpectedByte { .. } => None,
Self::Unexpected(err) => Some(err.source().unwrap_or(err.as_ref())),
Self::Utf8(err) => Some(err as &(dyn std::error::Error + 'static)),
}
}
}
impl From<std::io::Error> for ProtocolError {
fn from(value: std::io::Error) -> Self {
Self::IO(value)
}
}
impl From<BoxError> for ProtocolError {
fn from(value: BoxError) -> Self {
Self::Unexpected(value)
}
}
impl From<Utf8Error> for ProtocolError {
fn from(value: Utf8Error) -> Self {
Self::Utf8(value)
}
}
impl From<ReadError> for ProtocolError {
fn from(value: ReadError) -> Self {
match value {
ReadError::IO(error) => Self::IO(error),
ReadError::UnexpectedByte { pos, byte } => Self::UnexpectedByte { pos, byte },
ReadError::Unexpected(error) => Self::Unexpected(error),
}
}
}