use core::fmt;
use std::io;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum SerializeErrorKind {
IoError(io::ErrorKind),
InvalidValue(&'static str),
DepthLimit,
BufferFull,
Message(&'static str),
}
#[derive(Debug, Clone)]
pub struct SerializeError {
pub kind: SerializeErrorKind,
pub context: Option<String>,
}
impl SerializeError {
pub fn new(kind: SerializeErrorKind) -> Self {
Self {
kind,
context: None,
}
}
pub fn with_context(mut self, ctx: impl Into<String>) -> Self {
self.context = Some(ctx.into());
self
}
pub fn from_io_error(err: io::Error) -> Self {
Self {
kind: SerializeErrorKind::IoError(err.kind()),
context: Some(err.to_string()),
}
}
pub fn invalid_value(msg: &'static str) -> Self {
Self::new(SerializeErrorKind::InvalidValue(msg))
}
pub fn depth_limit() -> Self {
Self::new(SerializeErrorKind::DepthLimit)
}
pub fn message(msg: &'static str) -> Self {
Self::new(SerializeErrorKind::Message(msg))
}
}
impl fmt::Display for SerializeError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match &self.kind {
SerializeErrorKind::IoError(kind) => {
write!(f, "I/O error: {:?}", kind)?;
}
SerializeErrorKind::InvalidValue(msg) => {
write!(f, "invalid value: {}", msg)?;
}
SerializeErrorKind::DepthLimit => {
write!(f, "depth limit exceeded")?;
}
SerializeErrorKind::BufferFull => {
write!(f, "buffer full")?;
}
SerializeErrorKind::Message(msg) => {
write!(f, "{}", msg)?;
}
}
if let Some(ctx) = &self.context {
write!(f, " - {}", ctx)?;
}
Ok(())
}
}
impl std::error::Error for SerializeError {}
impl From<io::Error> for SerializeError {
fn from(err: io::Error) -> Self {
Self::from_io_error(err)
}
}