use std::error::Error;
use std::fmt::{self, Display, Formatter};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum InvalidPolicyKind {
ZeroInterval,
ZeroRatePerMinute,
IntervalOutOfRange,
}
#[derive(Debug)]
pub struct InvalidPolicyError {
kind: InvalidPolicyKind,
message: &'static str,
}
impl InvalidPolicyError {
pub fn kind(&self) -> InvalidPolicyKind {
self.kind
}
pub fn message(&self) -> &'static str {
self.message
}
pub(crate) fn zero_interval() -> Self {
Self {
kind: InvalidPolicyKind::ZeroInterval,
message: "min interval must be greater than zero",
}
}
pub(crate) fn zero_rpm() -> Self {
Self {
kind: InvalidPolicyKind::ZeroRatePerMinute,
message: "per-minute rate must be greater than zero",
}
}
pub(crate) fn interval_out_of_range() -> Self {
Self {
kind: InvalidPolicyKind::IntervalOutOfRange,
message: "policy interval is too large to represent",
}
}
}
impl Display for InvalidPolicyError {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.write_str(self.message)
}
}
impl Error for InvalidPolicyError {}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum RateLimitErrorKind {
InvalidPolicy,
Connection,
Backend,
Time,
Unknown,
}
#[derive(Debug)]
pub enum RateLimitError {
InvalidPolicy(InvalidPolicyError),
Backend {
kind: RateLimitErrorKind,
source: Box<dyn Error + Send + Sync>,
},
}
impl RateLimitError {
pub fn kind(&self) -> RateLimitErrorKind {
match self {
Self::InvalidPolicy(_) => RateLimitErrorKind::InvalidPolicy,
Self::Backend { kind, .. } => *kind,
}
}
#[cfg(feature = "valkey")]
pub(crate) fn backend<E>(kind: RateLimitErrorKind, source: E) -> Self
where
E: Error + Send + Sync + 'static,
{
Self::Backend {
kind,
source: Box::new(source),
}
}
}
impl Display for RateLimitError {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
Self::InvalidPolicy(error) => write!(f, "invalid policy: {error}"),
Self::Backend { source, .. } => write!(f, "{source}"),
}
}
}
impl Error for RateLimitError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
match self {
Self::InvalidPolicy(error) => Some(error),
Self::Backend { source, .. } => Some(source.as_ref()),
}
}
}
impl From<InvalidPolicyError> for RateLimitError {
fn from(value: InvalidPolicyError) -> Self {
Self::InvalidPolicy(value)
}
}
#[cfg(feature = "valkey")]
#[derive(Debug)]
pub enum ValkeyError {
Redis(redis::RedisError),
InvalidTime(std::time::SystemTimeError),
IntervalOutOfRange(std::num::TryFromIntError),
}
#[cfg(feature = "valkey")]
impl Display for ValkeyError {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
Self::Redis(error) => write!(f, "{error}"),
Self::InvalidTime(error) => write!(f, "{error}"),
Self::IntervalOutOfRange(error) => write!(f, "{error}"),
}
}
}
#[cfg(feature = "valkey")]
impl Error for ValkeyError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
match self {
Self::Redis(error) => Some(error),
Self::InvalidTime(error) => Some(error),
Self::IntervalOutOfRange(error) => Some(error),
}
}
}