1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
use std::{convert::Infallible, error::Error as StdError, fmt::Display};

use crate::io::Id;

#[derive(Debug)]
pub enum Error {
    Protocol(ProtocolError),
    Io(std::io::Error),
    Serialize(Option<bincode::Error>),
    Driver,
    Spawner,
    Other(Box<dyn StdError + Send + Sync + 'static>),
    Unspecified,
}

impl Display for Error {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Error::Protocol(e) => {
                write!(f, "protocol error: {}", e)
            }
            Error::Io(e) => {
                write!(f, "io error: {}", e)
            }
            Error::Serialize(e) => {
                write!(f, "serialize error: ")?;
                if let Some(e) = e {
                    write!(f, "{}", e)
                } else {
                    write!(f, "internal error")
                }
            }
            Error::Driver => {
                write!(f, "driver stopped unexpectedly")
            }
            Error::Spawner => {
                write!(f, "spawner stopped unexpectedly")
            }
            Error::Other(e) => {
                write!(f, "other error: {}", e)
            }
            Error::Unspecified => {
                write!(f, "unspecified error")
            }
        }
    }
}

impl StdError for Error {
    fn source(&self) -> Option<&(dyn StdError + 'static)> {
        match self {
            Error::Io(e) => Some(e),
            Error::Serialize(e) => e.as_ref().map(|e| e.as_ref() as &(dyn StdError + 'static)),
            Error::Other(e) => Some(e.as_ref() as &(dyn StdError + 'static)),
            _ => None,
        }
    }
}

impl From<std::io::Error> for Error {
    fn from(e: std::io::Error) -> Self {
        Self::Io(e)
    }
}

impl From<Infallible> for Error {
    fn from(_: Infallible) -> Self {
        unreachable!()
    }
}

impl<E: std::error::Error + Sync + Send + 'static> From<Box<E>> for Error {
    fn from(e: Box<E>) -> Self {
        Self::Other(e)
    }
}

// TODO more details
#[derive(Debug)]
pub enum ProtocolError {
    MartianResponse,
    ResponseMismatch(Id),
}

impl Display for ProtocolError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            ProtocolError::MartianResponse => {
                write!(f, "response of non-exist request")
            }
            ProtocolError::ResponseMismatch(_) => {
                write!(f, "response for different function")
            }
        }
    }
}

impl StdError for ProtocolError {}

impl From<ProtocolError> for Error {
    fn from(e: ProtocolError) -> Self {
        Self::Protocol(e)
    }
}

pub type Result<T> = std::result::Result<T, Error>;