redust_resp/
error.rs

1use std::borrow::Cow;
2
3use serde::{de, ser};
4use thiserror::Error;
5
6use crate::parser;
7
8type NomError<T> = nom::error::Error<T>;
9
10fn transform_parse_err<T, I>(
11	err: nom::Err<NomError<I>>,
12	map_input: impl FnOnce(I) -> T,
13) -> nom::Err<NomError<T>> {
14	let make_err = |e: NomError<I>| NomError {
15		input: map_input(e.input),
16		code: e.code,
17	};
18
19	match err {
20		nom::Err::Error(e) => nom::Err::Error(make_err(e)),
21		nom::Err::Failure(e) => nom::Err::Failure(make_err(e)),
22		nom::Err::Incomplete(needed) => nom::Err::Incomplete(needed),
23	}
24}
25
26/// Errors that can be encountered when interacting with RESP.
27#[derive(Debug, Error)]
28pub enum Error<'a> {
29	/// Serialization error.
30	#[error("{0}")]
31	Message(Cow<'a, str>),
32	/// An IO error occured when writing to the buffer.
33	#[error("io error: {0}")]
34	Io(#[from] std::io::Error),
35	/// Invalid RESP syntax.
36	#[error("parse error: {0}")]
37	Parse(parser::Error<'a>),
38	/// An error was indicated by the data.
39	#[error("Redis error: {0}")]
40	Redis(Cow<'a, str>),
41}
42
43impl Error<'_> {
44	/// Convert this error into an owned error.
45	pub fn into_owned(self) -> Error<'static> {
46		match self {
47			Self::Message(msg) => Error::Message(msg.into_owned().into()),
48			Self::Io(err) => Error::Io(err),
49			Self::Parse(err) => Error::Parse(transform_parse_err(err, |i| i.into_owned().into())),
50			Self::Redis(msg) => Error::Redis(msg.into_owned().into()),
51		}
52	}
53
54	/// Whether this error is transient (i.e. the source is still valid)
55	pub fn is_transient(&self) -> bool {
56		matches!(self, Self::Redis(_))
57	}
58}
59
60impl ser::Error for Error<'_> {
61	fn custom<T>(msg: T) -> Self
62	where
63		T: std::fmt::Display,
64	{
65		Self::Message(msg.to_string().into())
66	}
67}
68
69impl de::Error for Error<'_> {
70	fn custom<T>(msg: T) -> Self
71	where
72		T: std::fmt::Display,
73	{
74		Self::Message(msg.to_string().into())
75	}
76}
77
78impl<'a> From<parser::Error<'a>> for Error<'a> {
79	fn from(err: parser::Error<'a>) -> Self {
80		Self::Parse(err)
81	}
82}
83
84impl<'a> From<parser::RawError<'a>> for Error<'a> {
85	fn from(err: parser::RawError<'a>) -> Self {
86		Self::Parse(transform_parse_err(err, |i| i.into()))
87	}
88}
89
90/// Result with an error type defaulting to [enum@Error].
91pub type Result<'a, T, E = Error<'a>> = std::result::Result<T, E>;