Skip to main content

rate_limiter/
error.rs

1use std::error::Error;
2use std::fmt::{self, Display, Formatter};
3
4#[derive(Debug, Clone, Copy, PartialEq, Eq)]
5pub enum InvalidPolicyKind {
6    ZeroInterval,
7    ZeroRatePerMinute,
8    IntervalOutOfRange,
9}
10
11#[derive(Debug)]
12pub struct InvalidPolicyError {
13    kind: InvalidPolicyKind,
14    message: &'static str,
15}
16
17impl InvalidPolicyError {
18    pub fn kind(&self) -> InvalidPolicyKind {
19        self.kind
20    }
21
22    pub fn message(&self) -> &'static str {
23        self.message
24    }
25
26    pub(crate) fn zero_interval() -> Self {
27        Self {
28            kind: InvalidPolicyKind::ZeroInterval,
29            message: "min interval must be greater than zero",
30        }
31    }
32
33    pub(crate) fn zero_rpm() -> Self {
34        Self {
35            kind: InvalidPolicyKind::ZeroRatePerMinute,
36            message: "per-minute rate must be greater than zero",
37        }
38    }
39
40    pub(crate) fn interval_out_of_range() -> Self {
41        Self {
42            kind: InvalidPolicyKind::IntervalOutOfRange,
43            message: "policy interval is too large to represent",
44        }
45    }
46}
47
48impl Display for InvalidPolicyError {
49    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
50        f.write_str(self.message)
51    }
52}
53
54impl Error for InvalidPolicyError {}
55
56#[derive(Debug, Clone, Copy, PartialEq, Eq)]
57pub enum RateLimitErrorKind {
58    InvalidPolicy,
59    Connection,
60    Backend,
61    Time,
62    Unknown,
63}
64
65#[derive(Debug)]
66pub enum RateLimitError {
67    InvalidPolicy(InvalidPolicyError),
68    Backend {
69        kind: RateLimitErrorKind,
70        source: Box<dyn Error + Send + Sync>,
71    },
72}
73
74impl RateLimitError {
75    pub fn kind(&self) -> RateLimitErrorKind {
76        match self {
77            Self::InvalidPolicy(_) => RateLimitErrorKind::InvalidPolicy,
78            Self::Backend { kind, .. } => *kind,
79        }
80    }
81
82    #[cfg(feature = "valkey")]
83    pub(crate) fn backend<E>(kind: RateLimitErrorKind, source: E) -> Self
84    where
85        E: Error + Send + Sync + 'static,
86    {
87        Self::Backend {
88            kind,
89            source: Box::new(source),
90        }
91    }
92}
93
94impl Display for RateLimitError {
95    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
96        match self {
97            Self::InvalidPolicy(error) => write!(f, "invalid policy: {error}"),
98            Self::Backend { source, .. } => write!(f, "{source}"),
99        }
100    }
101}
102
103impl Error for RateLimitError {
104    fn source(&self) -> Option<&(dyn Error + 'static)> {
105        match self {
106            Self::InvalidPolicy(error) => Some(error),
107            Self::Backend { source, .. } => Some(source.as_ref()),
108        }
109    }
110}
111
112impl From<InvalidPolicyError> for RateLimitError {
113    fn from(value: InvalidPolicyError) -> Self {
114        Self::InvalidPolicy(value)
115    }
116}
117
118#[cfg(feature = "valkey")]
119#[derive(Debug)]
120pub enum ValkeyError {
121    Redis(redis::RedisError),
122    InvalidTime(std::time::SystemTimeError),
123    IntervalOutOfRange(std::num::TryFromIntError),
124}
125
126#[cfg(feature = "valkey")]
127impl Display for ValkeyError {
128    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
129        match self {
130            Self::Redis(error) => write!(f, "{error}"),
131            Self::InvalidTime(error) => write!(f, "{error}"),
132            Self::IntervalOutOfRange(error) => write!(f, "{error}"),
133        }
134    }
135}
136
137#[cfg(feature = "valkey")]
138impl Error for ValkeyError {
139    fn source(&self) -> Option<&(dyn Error + 'static)> {
140        match self {
141            Self::Redis(error) => Some(error),
142            Self::InvalidTime(error) => Some(error),
143            Self::IntervalOutOfRange(error) => Some(error),
144        }
145    }
146}