#[derive(Debug)]
pub struct Error {
pub(crate) inner: private::InnerError,
}
impl std::error::Error for Error {}
impl std::fmt::Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.inner)
}
}
impl From<private::InnerError> for Error {
fn from(error: private::InnerError) -> Error {
Self { inner: error }
}
}
pub enum ParseUpdateError<Body> {
UnknownUpdate(crate::Message<Body>),
InvalidUpdate(crate::MessageHeader, Box<dyn std::error::Error + Send>),
}
pub enum RecvMessageError<Body> {
Other(Error),
UnknownStream(crate::Message<Body>),
UnknownRequest(crate::ReceivedRequestHandle<Body>, Body),
InvalidStream(crate::MessageHeader, Box<dyn std::error::Error + Send>),
InvalidRequest(crate::ReceivedRequestHandle<Body>, Box<dyn std::error::Error + Send>),
}
impl Error {
pub fn io_error(error: std::io::Error) -> Self {
private::InnerError::from(error).into()
}
pub fn message_too_short(message_len: usize) -> Self {
private::InnerError::MessageTooShort { message_len }.into()
}
pub fn invalid_message_type(value: u32) -> Self {
private::InnerError::InvalidMessageType { value }.into()
}
pub fn payload_too_large(body_len: usize, max_len: usize) -> Self {
private::InnerError::PayloadTooLarge { body_len, max_len }.into()
}
pub fn unexpected_service_id(service_id: i32) -> Self {
private::InnerError::UnexpectedServiceId { service_id }.into()
}
pub fn encode_failed(inner: Box<dyn std::error::Error + Send>) -> Self {
private::InnerError::EncodeFailed(inner).into()
}
pub fn decode_failed(inner: Box<dyn std::error::Error + Send>) -> Self {
private::InnerError::DecodeFailed(inner).into()
}
pub fn remote_error(message: String) -> Self {
private::InnerError::RemoteError(message).into()
}
pub fn custom(message: String) -> Self {
private::InnerError::Custom(message).into()
}
pub fn is_connection_aborted(&self) -> bool {
if let private::InnerError::Io(e) = &self.inner {
e.kind() == std::io::ErrorKind::ConnectionAborted
} else {
false
}
}
pub fn is_unexpected_message_type(&self) -> bool {
matches!(&self.inner, private::InnerError::UnexpectedMessageType(_))
}
pub fn is_remote_error(&self) -> bool {
matches!(&self.inner, private::InnerError::RemoteError(_))
}
pub fn as_remote_error(&self) -> Option<&str> {
if let private::InnerError::RemoteError(msg) = &self.inner {
Some(msg)
} else {
None
}
}
pub fn into_remote_error(self) -> Option<String> {
if let private::InnerError::RemoteError(msg) = self.inner {
Some(msg)
} else {
None
}
}
}
impl<Body> RecvMessageError<Body> {
pub fn is_connection_aborted(&self) -> bool {
if let Self::Other(e) = self {
e.is_connection_aborted()
} else {
false
}
}
pub fn request_handle(&self) -> Option<&crate::ReceivedRequestHandle<Body>> {
match self {
Self::Other(_error) => None,
Self::UnknownStream(_message) => None,
Self::UnknownRequest(request, _body) => Some(request),
Self::InvalidStream(_message, _error) => None,
Self::InvalidRequest(request, _error) => Some(request),
}
}
pub fn request_handle_mut(&mut self) -> Option<&mut crate::ReceivedRequestHandle<Body>> {
match self {
Self::Other(_error) => None,
Self::UnknownStream(_message) => None,
Self::UnknownRequest(request, _body) => Some(request),
Self::InvalidStream(_message, _error) => None,
Self::InvalidRequest(request, _error) => Some(request),
}
}
}
impl From<std::io::Error> for Error {
fn from(other: std::io::Error) -> Self {
Self::io_error(other)
}
}
impl<Body> From<Error> for RecvMessageError<Body> {
fn from(other: Error) -> Self {
Self::Other(other)
}
}
impl<Body> std::error::Error for ParseUpdateError<Body> {}
impl<Body> std::error::Error for RecvMessageError<Body> {}
impl<Body> std::fmt::Display for ParseUpdateError<Body> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::UnknownUpdate(message) => write!(f, "received unknown update with service ID {}", message.header.service_id),
Self::InvalidUpdate(header, error) => write!(f, "received invalid update with service ID {}: {}", header.service_id, error),
}
}
}
impl<Body> std::fmt::Display for RecvMessageError<Body> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Other(e) => write!(f, "{}", e),
Self::UnknownStream(message) => write!(f, "received unknown stream message with service ID {}", message.header.service_id),
Self::InvalidStream(header, error) => write!(f, "received invalid stream message with service ID {}: {}", header.service_id, error),
Self::UnknownRequest(request, _body) => write!(f, "received unknown request message with service ID {}", request.service_id()),
Self::InvalidRequest(request, error) => write!(f, "received invalid request message with service ID {}: {}", request.service_id(), error),
}
}
}
impl<Body> std::fmt::Debug for ParseUpdateError<Body> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::UnknownUpdate(message) => f.debug_tuple("UnknownUpdate").field(message).finish(),
Self::InvalidUpdate(header, error) => f.debug_tuple("InvalidUpdate").field(header).field(error).finish(),
}
}
}
impl<Body> std::fmt::Debug for RecvMessageError<Body> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Other(e) => f.debug_tuple("Other").field(e).finish(),
Self::UnknownStream(message) => f.debug_tuple("UnknownStream").field(message).finish(),
Self::UnknownRequest(request, _body) => f.debug_tuple("UnknownStream").field(request).finish(),
Self::InvalidStream(header, error) => f.debug_tuple("InvalidStread").field(header).field(error).finish(),
Self::InvalidRequest(request, error) => f.debug_tuple("InvalidRequest").field(request).field(error).finish(),
}
}
}
pub(crate) mod private {
use super::*;
pub(crate) fn connection_aborted() -> Error {
InnerError::from(std::io::Error::from(std::io::ErrorKind::ConnectionAborted)).into()
}
#[derive(Debug)]
#[doc(hidden)]
pub enum InnerError {
Io(std::io::Error),
MessageTooShort { message_len: usize },
InvalidMessageType {
value: u32,
},
PayloadTooLarge {
body_len: usize,
max_len: usize,
},
DuplicateRequestId {
request_id: u32,
},
UnknownRequestId {
request_id: u32,
},
UnexpectedMessageType(UnexpectedMessageType),
UnexpectedServiceId {
service_id: i32,
},
NoFreeRequestIdFound,
RequestClosed,
EncodeFailed(Box<dyn std::error::Error + Send>),
DecodeFailed(Box<dyn std::error::Error + Send>),
RemoteError(String),
Custom(String),
}
impl From<std::io::Error> for private::InnerError {
fn from(error: std::io::Error) -> Self {
private::InnerError::Io(error)
}
}
impl From<UnexpectedMessageType> for private::InnerError {
fn from(error: UnexpectedMessageType) -> Self {
private::InnerError::UnexpectedMessageType(error)
}
}
impl std::error::Error for InnerError {}
impl std::fmt::Display for InnerError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
InnerError::Io(error) => write!(f, "{}", error),
InnerError::MessageTooShort { message_len } => write!(
f,
"the message is too short to be valid: need at least {} for the header, got only {message_len} bytes",
crate::HEADER_LEN
),
InnerError::InvalidMessageType { value } => write!(f, "invalid message type: expected a value in the range [0..4], got {value}"),
InnerError::PayloadTooLarge { body_len, max_len } => {
write!(f, "payload too large: maximum payload size is {max_len}, got {body_len}")
},
InnerError::DuplicateRequestId { request_id } => write!(
f,
"duplicate request ID: request ID {request_id} is already associated with an open request"
),
InnerError::UnknownRequestId { request_id } => {
write!(f, "unknown request ID: request ID {request_id} is not associated with an open request")
},
InnerError::UnexpectedMessageType(error) => write!(f, "{}", error),
InnerError::UnexpectedServiceId { service_id } => write!(f, "unexpected service ID: {service_id}"),
InnerError::NoFreeRequestIdFound => write!(f, "no free request ID was found"),
InnerError::RequestClosed => write!(f, "the request is already closed"),
InnerError::EncodeFailed(error) => write!(f, "{}", error),
InnerError::DecodeFailed(error) => write!(f, "{}", error),
InnerError::RemoteError(error) => write!(f, "{}", error),
InnerError::Custom(error) => write!(f, "{}", error),
}
}
}
#[allow(dead_code)] pub fn check_message_too_short(message_len: usize) -> Result<(), InnerError> {
if message_len >= crate::HEADER_LEN as usize {
Ok(())
} else {
Err(InnerError::MessageTooShort { message_len })
}
}
pub fn check_payload_too_large(body_len: usize, max_len: usize) -> Result<(), InnerError> {
if body_len <= max_len {
Ok(())
} else {
Err(InnerError::PayloadTooLarge { body_len, max_len })
}
}
#[derive(Debug, Clone)]
pub struct UnexpectedMessageType {
pub value: crate::MessageType,
pub expected: crate::MessageType,
}
impl std::error::Error for UnexpectedMessageType {}
impl std::fmt::Display for UnexpectedMessageType {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
let to_str = |kind| match kind {
crate::MessageType::Request => "a request message",
crate::MessageType::Response => "a response message",
crate::MessageType::RequesterUpdate => "an update message",
crate::MessageType::ResponderUpdate => "an update message",
crate::MessageType::Stream => "a streaming message",
};
write!(
f,
"unexpected message type: expected {}, got {}",
to_str(self.expected),
to_str(self.value)
)
}
}
}