use std::{borrow::Cow, str::Utf8Error};
use serde::{de, ser};
use thiserror::Error;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Needed {
Unknown,
Size(usize),
}
#[derive(Debug, Clone, PartialEq, Eq, Error)]
pub enum ParseError {
#[error("incomplete data")]
Incomplete(Needed),
#[error("expected {:?}, found {:?}", char::from(*.expected), char::from(*.found))]
Unexpected {
expected: u8,
found: u8,
},
#[error("unknown type {:?}", char::from(*.0))]
Type(u8),
#[error("expected CRLF")]
Crlf,
#[error("invalid integer")]
Integer,
#[error("invalid length {0}")]
Length(i64),
#[error("invalid UTF-8: {0}")]
Utf8(#[from] Utf8Error),
}
#[derive(Debug, Error)]
pub enum Error<'a> {
#[error("{0}")]
Message(Cow<'a, str>),
#[error("io error: {0}")]
Io(#[from] std::io::Error),
#[error("parse error: {0}")]
Parse(#[from] ParseError),
#[error("Redis error: {0}")]
Redis(Cow<'a, str>),
}
impl Error<'_> {
pub fn into_owned(self) -> Error<'static> {
match self {
Self::Message(msg) => Error::Message(msg.into_owned().into()),
Self::Io(err) => Error::Io(err),
Self::Parse(err) => Error::Parse(err),
Self::Redis(msg) => Error::Redis(msg.into_owned().into()),
}
}
pub fn is_transient(&self) -> bool {
matches!(self, Self::Redis(_))
}
}
impl ser::Error for Error<'_> {
fn custom<T>(msg: T) -> Self
where
T: std::fmt::Display,
{
Self::Message(msg.to_string().into())
}
}
impl de::Error for Error<'_> {
fn custom<T>(msg: T) -> Self
where
T: std::fmt::Display,
{
Self::Message(msg.to_string().into())
}
}
pub type Result<'a, T, E = Error<'a>> = std::result::Result<T, E>;