1use std::{borrow::Cow, str::Utf8Error};
2
3use serde::{de, ser};
4use thiserror::Error;
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
8pub enum Needed {
9 Unknown,
11 Size(usize),
13}
14
15#[derive(Debug, Clone, PartialEq, Eq, Error)]
17pub enum ParseError {
18 #[error("incomplete data")]
20 Incomplete(Needed),
21 #[error("expected {:?}, found {:?}", char::from(*.expected), char::from(*.found))]
23 Unexpected {
24 expected: u8,
26 found: u8,
28 },
29 #[error("unknown type {:?}", char::from(*.0))]
31 Type(u8),
32 #[error("expected CRLF")]
34 Crlf,
35 #[error("invalid integer")]
37 Integer,
38 #[error("invalid length {0}")]
40 Length(i64),
41 #[error("invalid UTF-8: {0}")]
43 Utf8(#[from] Utf8Error),
44}
45
46#[derive(Debug, Error)]
48pub enum Error<'a> {
49 #[error("{0}")]
51 Message(Cow<'a, str>),
52 #[error("io error: {0}")]
54 Io(#[from] std::io::Error),
55 #[error("parse error: {0}")]
57 Parse(#[from] ParseError),
58 #[error("Redis error: {0}")]
60 Redis(Cow<'a, str>),
61}
62
63impl Error<'_> {
64 pub fn into_owned(self) -> Error<'static> {
66 match self {
67 Self::Message(msg) => Error::Message(msg.into_owned().into()),
68 Self::Io(err) => Error::Io(err),
69 Self::Parse(err) => Error::Parse(err),
70 Self::Redis(msg) => Error::Redis(msg.into_owned().into()),
71 }
72 }
73
74 pub fn is_transient(&self) -> bool {
76 matches!(self, Self::Redis(_))
77 }
78}
79
80impl ser::Error for Error<'_> {
81 fn custom<T>(msg: T) -> Self
82 where
83 T: std::fmt::Display,
84 {
85 Self::Message(msg.to_string().into())
86 }
87}
88
89impl de::Error for Error<'_> {
90 fn custom<T>(msg: T) -> Self
91 where
92 T: std::fmt::Display,
93 {
94 Self::Message(msg.to_string().into())
95 }
96}
97
98pub type Result<'a, T, E = Error<'a>> = std::result::Result<T, E>;