via 2.0.0-gm.7

An async multi-threaded web framework for people who appreciate simplicity.
Documentation
use std::fmt::{self, Display, Formatter};
use std::ops::ControlFlow::{Break, Continue};
use tokio_websockets::Error as WebSocketError;

use crate::error::Error;

type ControlFlow<T> = std::ops::ControlFlow<T, T>;
pub type Result<T = ()> = std::result::Result<T, ControlFlow<Error>>;

pub trait ResultExt {
    type Output;
    fn or_break(self) -> Result<Self::Output>;
    fn or_continue(self) -> Result<Self::Output>;
}

#[derive(Debug)]
pub enum ErrorKind {
    Listener(Error),
    Socket(WebSocketError),
}

pub fn try_rescue_ws(error: WebSocketError) -> ControlFlow<Option<ErrorKind>> {
    let into_control_flow = match &error {
        WebSocketError::PayloadTooLong { .. } | WebSocketError::Protocol(_) => Continue,
        WebSocketError::Io(source) => match source.kind() {
            std::io::ErrorKind::Interrupted
            | std::io::ErrorKind::TimedOut
            | std::io::ErrorKind::WouldBlock
            | std::io::ErrorKind::WriteZero => Continue,
            _ => Break,
        },
        _ => Break,
    };

    into_control_flow(Some(error.into()))
}

impl ErrorKind {
    pub const CLOSED: Self = Self::Socket(WebSocketError::AlreadyClosed);
}

impl std::error::Error for ErrorKind {}

impl Display for ErrorKind {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        match self {
            Self::Listener(error) => Display::fmt(error, f),
            Self::Socket(error) => Display::fmt(error, f),
        }
    }
}

impl From<Error> for ErrorKind {
    fn from(error: Error) -> Self {
        Self::Listener(error)
    }
}

impl From<WebSocketError> for ErrorKind {
    fn from(error: WebSocketError) -> Self {
        Self::Socket(error)
    }
}

impl<T, E> ResultExt for std::result::Result<T, E>
where
    Error: From<E>,
{
    type Output = T;

    #[inline]
    fn or_break(self) -> Result<Self::Output> {
        self.map_err(|error| Break(error.into()))
    }

    #[inline]
    fn or_continue(self) -> Result<Self::Output> {
        self.map_err(|error| Continue(error.into()))
    }
}