use crate::codec::{
Err, ErrorCode, Key, KeyLength, MessageType, MetaData, MetaDataLength, NumKeyValuePairs,
PathLength, RequestPattern, RequestPatternLength, ValueLength,
};
use std::{fmt, io, net::AddrParseError, num::ParseIntError, string::FromUtf8Error};
use tokio::sync::{broadcast, mpsc::error::SendError, oneshot};
use tokio_tungstenite::tungstenite;
#[derive(Debug)]
pub enum DecodeError {
UndefinedType(MessageType),
IoError(io::Error),
FromUtf8Error(FromUtf8Error),
UndefinedErrorCode(ErrorCode),
SerDeError(serde_json::Error),
}
impl std::error::Error for DecodeError {}
impl fmt::Display for DecodeError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
DecodeError::UndefinedType(mtype) => write!(f, "undefined message type: {mtype})",),
DecodeError::IoError(e) => e.fmt(f),
DecodeError::FromUtf8Error(e) => e.fmt(f),
DecodeError::SerDeError(e) => e.fmt(f),
DecodeError::UndefinedErrorCode(error_code) => {
write!(f, "undefined error code: {error_code})",)
}
}
}
}
impl From<io::Error> for DecodeError {
fn from(e: io::Error) -> Self {
DecodeError::IoError(e)
}
}
impl From<FromUtf8Error> for DecodeError {
fn from(e: FromUtf8Error) -> Self {
DecodeError::FromUtf8Error(e)
}
}
impl From<serde_json::Error> for DecodeError {
fn from(e: serde_json::Error) -> Self {
DecodeError::SerDeError(e)
}
}
pub type DecodeResult<T> = std::result::Result<T, DecodeError>;
#[derive(Debug)]
pub enum EncodeError {
RequestPatternTooLong(usize),
KeyTooLong(usize),
ValueTooLong(usize),
MetaDataTooLong(usize),
PathTooLong(usize),
TooManyKeyValuePairs(usize),
TooManyProtocolVersions(usize),
IoError(io::Error),
}
impl std::error::Error for EncodeError {}
impl fmt::Display for EncodeError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
EncodeError::RequestPatternTooLong(len) => write!(
f,
"request pattern is too long : {} bytes (max {} bytes allowed)",
len,
RequestPatternLength::MAX
),
EncodeError::KeyTooLong(len) => write!(
f,
"key is too long : {} bytes (max {} bytes allowed)",
len,
KeyLength::MAX
),
EncodeError::ValueTooLong(len) => write!(
f,
"value is too long : {} bytes (max {} bytes allowed)",
len,
ValueLength::MAX
),
EncodeError::MetaDataTooLong(len) => write!(
f,
"meta data is too long : {} bytes (max {} bytes allowed)",
len,
MetaDataLength::MAX
),
EncodeError::PathTooLong(len) => write!(
f,
"path is too long : {} bytes (max {} bytes allowed)",
len,
PathLength::MAX
),
EncodeError::TooManyKeyValuePairs(len) => write!(
f,
"too many key/value pairs: {} (max {} allowed)",
len,
NumKeyValuePairs::MAX
),
EncodeError::TooManyProtocolVersions(len) => write!(
f,
"too many supported protocol versions pairs: {} (max {} allowed)",
len,
NumKeyValuePairs::MAX
),
EncodeError::IoError(ioe) => ioe.fmt(f),
}
}
}
impl From<io::Error> for EncodeError {
fn from(e: io::Error) -> Self {
EncodeError::IoError(e)
}
}
pub type EncodeResult<T> = std::result::Result<T, EncodeError>;
#[derive(Debug)]
pub enum ConfigError {
InvalidSeparator(String),
InvalidWildcard(String),
InvalidMultiWildcard(String),
InvalidPort(ParseIntError),
InvalidAddr(AddrParseError),
InvalidInterval(ParseIntError),
}
impl std::error::Error for ConfigError {}
impl fmt::Display for ConfigError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ConfigError::InvalidSeparator(str) => write!(
f,
"invalid separator: {str}; separator must be a single ASCII char"
),
ConfigError::InvalidWildcard(str) => write!(
f,
"invalid wildcard: {str}; wildcard must be a single ASCII char"
),
ConfigError::InvalidMultiWildcard(str) => write!(
f,
"invalid multi-wildcard: {str}; multi-wildcard must be a single ASCII char"
),
ConfigError::InvalidPort(e) => write!(f, "invalid port: {e}"),
ConfigError::InvalidAddr(e) => write!(f, "invalid address: {e}"),
ConfigError::InvalidInterval(e) => write!(f, "invalid port: {e}"),
}
}
}
pub trait ConfigIntContext<I> {
fn as_port(self) -> Result<I, ConfigError>;
fn as_interval(self) -> Result<I, ConfigError>;
}
impl<I> ConfigIntContext<I> for Result<I, ParseIntError> {
fn as_port(self) -> Result<I, ConfigError> {
self.map_err(ConfigError::InvalidPort)
}
fn as_interval(self) -> Result<I, ConfigError> {
self.map_err(ConfigError::InvalidInterval)
}
}
impl From<AddrParseError> for ConfigError {
fn from(e: AddrParseError) -> Self {
ConfigError::InvalidAddr(e)
}
}
pub type ConfigResult<T> = std::result::Result<T, ConfigError>;
pub trait Context<T, E: std::error::Error> {
fn context(self, metadata: impl FnOnce() -> String) -> Result<T, WorterbuchError>;
}
#[derive(Debug)]
pub enum WorterbuchError {
IllegalWildcard(RequestPattern),
IllegalMultiWildcard(RequestPattern),
MultiWildcardAtIllegalPosition(RequestPattern),
NoSuchValue(Key),
NotSubscribed,
IoError(io::Error, MetaData),
SerDeError(serde_json::Error, MetaData),
Other(Box<dyn std::error::Error + Send + Sync>, MetaData),
ServerResponse(Err),
}
impl std::error::Error for WorterbuchError {}
impl fmt::Display for WorterbuchError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
WorterbuchError::IllegalWildcard(rp) => {
write!(f, "Key contains illegal wildcard: {rp}")
}
WorterbuchError::IllegalMultiWildcard(rp) => {
write!(f, "Key contains illegal multi-wildcard: {rp}")
}
WorterbuchError::MultiWildcardAtIllegalPosition(rp) => {
write!(f, "Key contains multi-wildcard at illegal position: {rp}")
}
WorterbuchError::NoSuchValue(key) => write!(f, "no value for key '{key}'"),
WorterbuchError::NotSubscribed => write!(f, "no such subscription"),
WorterbuchError::IoError(e, meta) => write!(f, "{meta}: {e}"),
WorterbuchError::SerDeError(e, meta) => write!(f, "{meta}: {e}"),
WorterbuchError::Other(e, meta) => write!(f, "{meta}: {e}"),
WorterbuchError::ServerResponse(e) => {
write!(f, "error {}: {}", e.error_code, e.metadata)
}
}
}
}
impl<T> Context<T, io::Error> for Result<T, io::Error> {
fn context(self, metadata: impl FnOnce() -> String) -> Result<T, WorterbuchError> {
self.map_err(|e| WorterbuchError::IoError(e, metadata()))
}
}
impl<T> Context<T, serde_json::Error> for Result<T, serde_json::Error> {
fn context(self, metadata: impl FnOnce() -> String) -> Result<T, WorterbuchError> {
self.map_err(|e| WorterbuchError::SerDeError(e, metadata()))
}
}
impl<T, V: fmt::Debug + 'static + Send + Sync> Context<T, SendError<V>>
for Result<T, SendError<V>>
{
fn context(self, metadata: impl FnOnce() -> String) -> Result<T, WorterbuchError> {
self.map_err(|e| WorterbuchError::Other(Box::new(e), metadata()))
}
}
pub type WorterbuchResult<T> = std::result::Result<T, WorterbuchError>;
#[derive(Debug)]
pub enum ConnectionError {
IoError(io::Error),
EncodeError(EncodeError),
SendError(Box<dyn std::error::Error + Send + Sync>),
WebsocketError(tungstenite::Error),
TrySendError(Box<dyn std::error::Error + Send + Sync>),
RecvError(oneshot::error::RecvError),
BcRecvError(broadcast::error::RecvError),
WorterbuchError(WorterbuchError),
ConfigError(ConfigError),
}
impl std::error::Error for ConnectionError {}
impl fmt::Display for ConnectionError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::IoError(e) => fmt::Display::fmt(&e, f),
Self::EncodeError(e) => fmt::Display::fmt(&e, f),
Self::SendError(e) => fmt::Display::fmt(&e, f),
Self::WebsocketError(e) => fmt::Display::fmt(&e, f),
Self::TrySendError(e) => fmt::Display::fmt(&e, f),
Self::RecvError(e) => fmt::Display::fmt(&e, f),
Self::BcRecvError(e) => fmt::Display::fmt(&e, f),
Self::WorterbuchError(e) => fmt::Display::fmt(&e, f),
Self::ConfigError(e) => fmt::Display::fmt(&e, f),
}
}
}
pub type ConnectionResult<T> = std::result::Result<T, ConnectionError>;
impl From<EncodeError> for ConnectionError {
fn from(e: EncodeError) -> Self {
ConnectionError::EncodeError(e)
}
}
impl From<io::Error> for ConnectionError {
fn from(e: io::Error) -> Self {
ConnectionError::IoError(e)
}
}
impl<T: fmt::Debug + 'static + Send + Sync> From<SendError<T>> for ConnectionError {
fn from(e: SendError<T>) -> Self {
ConnectionError::SendError(Box::new(e))
}
}
impl From<tungstenite::Error> for ConnectionError {
fn from(e: tungstenite::Error) -> Self {
ConnectionError::WebsocketError(e)
}
}
impl From<oneshot::error::RecvError> for ConnectionError {
fn from(e: oneshot::error::RecvError) -> Self {
ConnectionError::RecvError(e)
}
}
impl From<broadcast::error::RecvError> for ConnectionError {
fn from(e: broadcast::error::RecvError) -> Self {
ConnectionError::BcRecvError(e)
}
}
impl From<ConfigError> for ConnectionError {
fn from(e: ConfigError) -> Self {
ConnectionError::ConfigError(e)
}
}