veilid/veilid-tools/src/network_result.rs

431 lines
16 KiB
Rust
Raw Normal View History

2022-07-14 20:57:34 +00:00
use super::*;
2022-11-27 02:37:23 +00:00
2022-07-14 20:57:34 +00:00
use core::fmt::{Debug, Display};
use core::result::Result;
use std::error::Error;
use std::io;
//////////////////////////////////////////////////////////////////
// Non-fallible network results conversions
pub trait NetworkResultExt<T> {
fn into_network_result(self) -> NetworkResult<T>;
}
impl<T> NetworkResultExt<T> for Result<T, TimeoutError> {
fn into_network_result(self) -> NetworkResult<T> {
self.ok()
.map(|v| NetworkResult::<T>::Value(v))
.unwrap_or(NetworkResult::<T>::Timeout)
}
}
pub trait IoNetworkResultExt<T> {
fn into_network_result(self) -> io::Result<NetworkResult<T>>;
}
impl<T> IoNetworkResultExt<T> for io::Result<T> {
fn into_network_result(self) -> io::Result<NetworkResult<T>> {
match self {
Ok(v) => Ok(NetworkResult::Value(v)),
#[cfg(feature = "io_error_more")]
Err(e) => match e.kind() {
io::ErrorKind::TimedOut => Ok(NetworkResult::Timeout),
2023-07-03 15:38:40 +00:00
io::ErrorKind::UnexpectedEof
| io::ErrorKind::ConnectionAborted
2022-07-14 20:57:34 +00:00
| io::ErrorKind::ConnectionRefused
| io::ErrorKind::ConnectionReset
| io::ErrorKind::HostUnreachable
| io::ErrorKind::NetworkUnreachable => Ok(NetworkResult::NoConnection(e)),
2022-10-04 17:09:03 +00:00
io::ErrorKind::AddrNotAvailable => Ok(NetworkResult::AlreadyExists(e)),
2022-07-14 20:57:34 +00:00
_ => Err(e),
},
#[cfg(not(feature = "io_error_more"))]
2022-08-04 16:48:19 +00:00
Err(e) => {
2022-08-19 16:49:18 +00:00
#[cfg(not(target_arch = "wasm32"))]
2022-08-04 16:48:19 +00:00
if let Some(os_err) = e.raw_os_error() {
if os_err == libc::EHOSTUNREACH || os_err == libc::ENETUNREACH {
return Ok(NetworkResult::NoConnection(e));
}
}
match e.kind() {
io::ErrorKind::TimedOut => Ok(NetworkResult::Timeout),
2023-07-03 15:38:40 +00:00
io::ErrorKind::UnexpectedEof
| io::ErrorKind::ConnectionAborted
2022-08-04 16:48:19 +00:00
| io::ErrorKind::ConnectionRefused
| io::ErrorKind::ConnectionReset => Ok(NetworkResult::NoConnection(e)),
2022-10-04 17:09:03 +00:00
io::ErrorKind::AddrNotAvailable => Ok(NetworkResult::AlreadyExists(e)),
2022-08-04 16:48:19 +00:00
_ => Err(e),
}
}
2022-07-14 20:57:34 +00:00
}
}
}
pub trait NetworkResultResultExt<T, E> {
fn into_result_network_result(self) -> Result<NetworkResult<T>, E>;
}
impl<T, E> NetworkResultResultExt<T, E> for NetworkResult<Result<T, E>> {
fn into_result_network_result(self) -> Result<NetworkResult<T>, E> {
match self {
NetworkResult::Timeout => Ok(NetworkResult::<T>::Timeout),
2023-06-21 17:40:12 +00:00
NetworkResult::ServiceUnavailable(s) => Ok(NetworkResult::<T>::ServiceUnavailable(s)),
2022-07-14 20:57:34 +00:00
NetworkResult::NoConnection(e) => Ok(NetworkResult::<T>::NoConnection(e)),
2022-10-04 17:09:03 +00:00
NetworkResult::AlreadyExists(e) => Ok(NetworkResult::<T>::AlreadyExists(e)),
2022-07-20 13:39:38 +00:00
NetworkResult::InvalidMessage(s) => Ok(NetworkResult::<T>::InvalidMessage(s)),
2022-07-14 20:57:34 +00:00
NetworkResult::Value(Ok(v)) => Ok(NetworkResult::<T>::Value(v)),
NetworkResult::Value(Err(e)) => Err(e),
}
}
}
pub trait FoldedNetworkResultExt<T> {
fn folded(self) -> io::Result<NetworkResult<T>>;
}
impl<T> FoldedNetworkResultExt<T> for io::Result<TimeoutOr<T>> {
fn folded(self) -> io::Result<NetworkResult<T>> {
match self {
Ok(TimeoutOr::Timeout) => Ok(NetworkResult::Timeout),
Ok(TimeoutOr::Value(v)) => Ok(NetworkResult::Value(v)),
#[cfg(feature = "io_error_more")]
Err(e) => match e.kind() {
io::ErrorKind::TimedOut => Ok(NetworkResult::Timeout),
io::ErrorKind::ConnectionAborted
| io::ErrorKind::ConnectionRefused
| io::ErrorKind::ConnectionReset
| io::ErrorKind::HostUnreachable
| io::ErrorKind::NetworkUnreachable => Ok(NetworkResult::NoConnection(e)),
2022-10-04 17:09:03 +00:00
io::ErrorKind::AddrNotAvailable => Ok(NetworkResult::AlreadyExists(e)),
2022-07-14 20:57:34 +00:00
_ => Err(e),
},
#[cfg(not(feature = "io_error_more"))]
2022-08-04 16:48:19 +00:00
Err(e) => {
2022-08-19 16:49:18 +00:00
#[cfg(not(target_arch = "wasm32"))]
2022-08-04 16:48:19 +00:00
if let Some(os_err) = e.raw_os_error() {
if os_err == libc::EHOSTUNREACH || os_err == libc::ENETUNREACH {
return Ok(NetworkResult::NoConnection(e));
}
}
match e.kind() {
io::ErrorKind::TimedOut => Ok(NetworkResult::Timeout),
io::ErrorKind::ConnectionAborted
| io::ErrorKind::ConnectionRefused
| io::ErrorKind::ConnectionReset => Ok(NetworkResult::NoConnection(e)),
2022-10-04 17:09:03 +00:00
io::ErrorKind::AddrNotAvailable => Ok(NetworkResult::AlreadyExists(e)),
2022-08-04 16:48:19 +00:00
_ => Err(e),
}
}
2022-07-14 20:57:34 +00:00
}
}
}
impl<T> FoldedNetworkResultExt<T> for io::Result<NetworkResult<T>> {
fn folded(self) -> io::Result<NetworkResult<T>> {
match self {
Ok(v) => Ok(v),
#[cfg(feature = "io_error_more")]
Err(e) => match e.kind() {
io::ErrorKind::TimedOut => Ok(NetworkResult::Timeout),
io::ErrorKind::ConnectionAborted
| io::ErrorKind::ConnectionRefused
| io::ErrorKind::ConnectionReset
| io::ErrorKind::HostUnreachable
| io::ErrorKind::NetworkUnreachable => Ok(NetworkResult::NoConnection(e)),
2022-10-04 17:09:03 +00:00
io::ErrorKind::AddrNotAvailable => Ok(NetworkResult::AlreadyExists(e)),
2022-07-14 20:57:34 +00:00
_ => Err(e),
},
#[cfg(not(feature = "io_error_more"))]
2022-08-04 16:48:19 +00:00
Err(e) => {
2022-08-19 16:49:18 +00:00
#[cfg(not(target_arch = "wasm32"))]
2022-08-04 16:48:19 +00:00
if let Some(os_err) = e.raw_os_error() {
if os_err == libc::EHOSTUNREACH || os_err == libc::ENETUNREACH {
return Ok(NetworkResult::NoConnection(e));
}
}
match e.kind() {
io::ErrorKind::TimedOut => Ok(NetworkResult::Timeout),
io::ErrorKind::ConnectionAborted
| io::ErrorKind::ConnectionRefused
| io::ErrorKind::ConnectionReset => Ok(NetworkResult::NoConnection(e)),
2022-10-04 17:09:03 +00:00
io::ErrorKind::AddrNotAvailable => Ok(NetworkResult::AlreadyExists(e)),
2022-08-04 16:48:19 +00:00
_ => Err(e),
}
}
2022-07-14 20:57:34 +00:00
}
}
}
//////////////////////////////////////////////////////////////////
// Non-fallible network result
2022-07-20 13:39:38 +00:00
#[must_use]
2022-07-14 20:57:34 +00:00
pub enum NetworkResult<T> {
Timeout,
2023-06-21 17:40:12 +00:00
ServiceUnavailable(String),
2022-07-14 20:57:34 +00:00
NoConnection(io::Error),
2022-10-04 17:09:03 +00:00
AlreadyExists(io::Error),
2022-07-20 13:39:38 +00:00
InvalidMessage(String),
2022-07-14 20:57:34 +00:00
Value(T),
}
impl<T> NetworkResult<T> {
pub fn timeout() -> Self {
Self::Timeout
}
2023-06-21 17:40:12 +00:00
pub fn service_unavailable<S: ToString>(s: S) -> Self {
Self::ServiceUnavailable(s.to_string())
2022-12-16 01:52:24 +00:00
}
2022-07-14 20:57:34 +00:00
pub fn no_connection(e: io::Error) -> Self {
Self::NoConnection(e)
}
2022-07-20 13:39:38 +00:00
pub fn no_connection_other<S: ToString>(s: S) -> Self {
Self::NoConnection(io::Error::new(io::ErrorKind::Other, s.to_string()))
}
pub fn invalid_message<S: ToString>(s: S) -> Self {
Self::InvalidMessage(s.to_string())
}
2022-10-04 17:09:03 +00:00
pub fn already_exists(e: io::Error) -> Self {
Self::AlreadyExists(e)
}
2022-07-14 20:57:34 +00:00
pub fn value(value: T) -> Self {
Self::Value(value)
}
pub fn is_timeout(&self) -> bool {
matches!(self, Self::Timeout)
}
pub fn is_no_connection(&self) -> bool {
matches!(self, Self::NoConnection(_))
}
2022-10-04 17:09:03 +00:00
pub fn is_already_exists(&self) -> bool {
matches!(self, Self::AlreadyExists(_))
}
2022-07-14 20:57:34 +00:00
pub fn is_value(&self) -> bool {
matches!(self, Self::Value(_))
}
2022-07-20 13:39:38 +00:00
pub fn map<X, F: Fn(T) -> X>(self, f: F) -> NetworkResult<X> {
match self {
Self::Timeout => NetworkResult::<X>::Timeout,
2023-06-21 17:40:12 +00:00
Self::ServiceUnavailable(s) => NetworkResult::<X>::ServiceUnavailable(s),
2022-07-20 13:39:38 +00:00
Self::NoConnection(e) => NetworkResult::<X>::NoConnection(e),
2022-10-04 17:09:03 +00:00
Self::AlreadyExists(e) => NetworkResult::<X>::AlreadyExists(e),
2022-07-20 13:39:38 +00:00
Self::InvalidMessage(s) => NetworkResult::<X>::InvalidMessage(s),
Self::Value(v) => NetworkResult::<X>::Value(f(v)),
}
}
2022-07-14 20:57:34 +00:00
pub fn into_result(self) -> Result<T, io::Error> {
match self {
Self::Timeout => Err(io::Error::new(io::ErrorKind::TimedOut, "Timed out")),
2023-06-21 17:40:12 +00:00
Self::ServiceUnavailable(s) => Err(io::Error::new(
2022-12-16 01:52:24 +00:00
io::ErrorKind::NotFound,
2023-06-21 17:40:12 +00:00
format!("Service unavailable: {}", s),
2022-12-16 01:52:24 +00:00
)),
2022-07-14 20:57:34 +00:00
Self::NoConnection(e) => Err(e),
2022-10-04 17:09:03 +00:00
Self::AlreadyExists(e) => Err(e),
2022-07-20 13:39:38 +00:00
Self::InvalidMessage(s) => Err(io::Error::new(
io::ErrorKind::InvalidData,
format!("Invalid message: {}", s),
)),
2022-07-14 20:57:34 +00:00
Self::Value(v) => Ok(v),
}
}
}
impl<T> From<NetworkResult<T>> for Option<T> {
fn from(t: NetworkResult<T>) -> Self {
match t {
NetworkResult::Value(v) => Some(v),
_ => None,
}
}
}
impl<T: Debug> Debug for NetworkResult<T> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
Self::Timeout => write!(f, "Timeout"),
2023-06-21 17:40:12 +00:00
Self::ServiceUnavailable(s) => f.debug_tuple("ServiceUnavailable").field(s).finish(),
2022-07-14 20:57:34 +00:00
Self::NoConnection(e) => f.debug_tuple("NoConnection").field(e).finish(),
2022-10-04 17:09:03 +00:00
Self::AlreadyExists(e) => f.debug_tuple("AlreadyExists").field(e).finish(),
2022-07-20 13:39:38 +00:00
Self::InvalidMessage(s) => f.debug_tuple("InvalidMessage").field(s).finish(),
2022-07-14 20:57:34 +00:00
Self::Value(v) => f.debug_tuple("Value").field(v).finish(),
}
}
}
2022-07-20 13:39:38 +00:00
impl<T> Display for NetworkResult<T> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
2022-07-14 20:57:34 +00:00
match self {
2022-07-20 13:39:38 +00:00
Self::Timeout => write!(f, "Timeout"),
2023-06-21 17:40:12 +00:00
Self::ServiceUnavailable(s) => write!(f, "ServiceUnavailable({})", s),
2022-07-20 13:39:38 +00:00
Self::NoConnection(e) => write!(f, "NoConnection({})", e.kind()),
2022-10-04 17:09:03 +00:00
Self::AlreadyExists(e) => write!(f, "AlreadyExists({})", e.kind()),
2022-07-20 13:39:38 +00:00
Self::InvalidMessage(s) => write!(f, "InvalidMessage({})", s),
Self::Value(_) => write!(f, "Value"),
2022-07-14 20:57:34 +00:00
}
}
}
2022-07-20 13:39:38 +00:00
2022-07-14 20:57:34 +00:00
impl<T: Debug + Display> Error for NetworkResult<T> {}
//////////////////////////////////////////////////////////////////
// Non-fallible network result macros
2023-06-25 18:09:22 +00:00
#[macro_export]
macro_rules! network_result_raise {
($r: expr) => {
match $r {
NetworkResult::Timeout => return Ok(NetworkResult::Timeout),
NetworkResult::ServiceUnavailable(s) => return Ok(NetworkResult::ServiceUnavailable(s)),
NetworkResult::NoConnection(e) => return Ok(NetworkResult::NoConnection(e)),
NetworkResult::AlreadyExists(e) => return Ok(NetworkResult::AlreadyExists(e)),
NetworkResult::InvalidMessage(s) => return Ok(NetworkResult::InvalidMessage(s)),
NetworkResult::Value(_) => panic!("Can not raise value"),
}
};
}
2022-07-14 20:57:34 +00:00
#[macro_export]
macro_rules! network_result_try {
($r: expr) => {
match $r {
NetworkResult::Timeout => return Ok(NetworkResult::Timeout),
2023-06-21 17:40:12 +00:00
NetworkResult::ServiceUnavailable(s) => return Ok(NetworkResult::ServiceUnavailable(s)),
2022-07-14 20:57:34 +00:00
NetworkResult::NoConnection(e) => return Ok(NetworkResult::NoConnection(e)),
2022-10-04 17:09:03 +00:00
NetworkResult::AlreadyExists(e) => return Ok(NetworkResult::AlreadyExists(e)),
2022-07-20 13:39:38 +00:00
NetworkResult::InvalidMessage(s) => return Ok(NetworkResult::InvalidMessage(s)),
NetworkResult::Value(v) => v,
}
};
($r:expr => $f:tt) => {
match $r {
NetworkResult::Timeout => {
$f;
return Ok(NetworkResult::Timeout);
}
2023-06-21 17:40:12 +00:00
NetworkResult::ServiceUnavailable(s) => {
2022-12-16 01:52:24 +00:00
$f;
2023-06-21 17:40:12 +00:00
return Ok(NetworkResult::ServiceUnavailable(s));
2022-12-16 01:52:24 +00:00
}
2022-07-20 13:39:38 +00:00
NetworkResult::NoConnection(e) => {
$f;
return Ok(NetworkResult::NoConnection(e));
}
2022-10-04 17:09:03 +00:00
NetworkResult::AlreadyExists(e) => {
$f;
return Ok(NetworkResult::AlreadyExists(e));
}
2022-07-20 13:39:38 +00:00
NetworkResult::InvalidMessage(s) => {
$f;
return Ok(NetworkResult::InvalidMessage(s));
}
NetworkResult::Value(v) => v,
}
};
}
2022-11-22 01:21:46 +00:00
#[macro_export]
macro_rules! log_network_result {
($text:expr) => {
2023-06-25 18:09:22 +00:00
cfg_if::cfg_if! {
2023-06-25 21:59:11 +00:00
if #[cfg(feature="network-result-extra")] {
2023-06-25 18:09:22 +00:00
info!(target: "network_result", "{}", format!("{}", $text))
} else {
debug!(target: "network_result", "{}", format!("{}", $text))
}
}
2022-11-22 01:21:46 +00:00
};
($fmt:literal, $($arg:expr),+) => {
2023-06-25 18:09:22 +00:00
cfg_if::cfg_if! {
2023-06-25 21:59:11 +00:00
if #[cfg(feature="network-result-extra")] {
2023-06-25 18:09:22 +00:00
info!(target: "network_result", "{}", format!($fmt, $($arg),+));
} else {
debug!(target: "network_result", "{}", format!($fmt, $($arg),+));
}
}
2022-11-22 01:21:46 +00:00
};
}
2022-07-20 13:39:38 +00:00
#[macro_export]
macro_rules! network_result_value_or_log {
2023-06-25 18:09:22 +00:00
($r:expr => $f:expr) => {
network_result_value_or_log!($r => [ "" ] $f )
};
($r:expr => [ $d:expr ] $f:expr) => { {
#[cfg(feature="network-result-extra")]
let __extra_message = $d;
#[cfg(not(feature="network-result-extra"))]
let __extra_message = "";
2022-07-20 13:39:38 +00:00
match $r {
NetworkResult::Timeout => {
2023-06-21 17:40:12 +00:00
log_network_result!(
2023-06-25 18:09:22 +00:00
"{} at {}@{}:{} in {}{}",
2023-06-21 17:40:12 +00:00
"Timeout",
file!(),
line!(),
column!(),
2023-06-25 18:09:22 +00:00
fn_name::uninstantiated!(),
__extra_message
2023-06-21 17:40:12 +00:00
);
2022-07-20 13:39:38 +00:00
$f
}
2023-06-25 18:09:22 +00:00
NetworkResult::ServiceUnavailable(ref s) => {
2022-12-16 01:52:24 +00:00
log_network_result!(
2023-06-25 18:09:22 +00:00
"{}({}) at {}@{}:{} in {}{}",
2023-06-08 18:07:09 +00:00
"ServiceUnavailable",
2023-06-21 17:40:12 +00:00
s,
2022-12-16 01:52:24 +00:00
file!(),
line!(),
2023-06-21 17:40:12 +00:00
column!(),
2023-06-25 18:09:22 +00:00
fn_name::uninstantiated!(),
__extra_message
2022-12-16 01:52:24 +00:00
);
$f
}
2023-06-25 18:09:22 +00:00
NetworkResult::NoConnection(ref e) => {
2022-11-22 01:21:46 +00:00
log_network_result!(
2023-06-25 18:09:22 +00:00
"{}({}) at {}@{}:{} in {}{}",
2023-06-08 18:07:09 +00:00
"No connection",
2022-11-22 01:21:46 +00:00
e.to_string(),
file!(),
line!(),
2023-06-21 17:40:12 +00:00
column!(),
2023-06-25 18:09:22 +00:00
fn_name::uninstantiated!(),
__extra_message
2022-11-22 01:21:46 +00:00
);
2022-07-20 13:39:38 +00:00
$f
}
2023-06-25 18:09:22 +00:00
NetworkResult::AlreadyExists(ref e) => {
2022-11-22 01:21:46 +00:00
log_network_result!(
2023-06-25 18:09:22 +00:00
"{}({}) at {}@{}:{} in {}{}",
2023-06-08 18:07:09 +00:00
"Already exists",
2022-11-22 01:21:46 +00:00
e.to_string(),
file!(),
line!(),
2023-06-21 17:40:12 +00:00
column!(),
2023-06-25 18:09:22 +00:00
fn_name::uninstantiated!(),
__extra_message
2022-11-22 01:21:46 +00:00
);
2022-10-04 17:09:03 +00:00
$f
}
2023-06-25 18:09:22 +00:00
NetworkResult::InvalidMessage(ref s) => {
2022-11-22 01:21:46 +00:00
log_network_result!(
2023-06-25 18:09:22 +00:00
"{}({}) at {}@{}:{} in {}{}",
2023-06-08 18:07:09 +00:00
"Invalid message",
2022-11-22 01:21:46 +00:00
s,
file!(),
line!(),
2023-06-21 17:40:12 +00:00
column!(),
2023-06-25 18:09:22 +00:00
fn_name::uninstantiated!(),
__extra_message
2022-11-22 01:21:46 +00:00
);
2022-07-20 13:39:38 +00:00
$f
}
2022-07-14 20:57:34 +00:00
NetworkResult::Value(v) => v,
}
2023-06-25 18:09:22 +00:00
} };
2022-07-14 20:57:34 +00:00
}