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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
use crate::query::QueryFailed;
use std::error;
use std::fmt::{Display, Formatter};
use std::io;
use std::string::FromUtf8Error;

/// The error type for the DB operations of the [`Client`], [`Query`] and associated structs and traits.
///
/// Errors mostly occur while communicating with the database, but can also happen e.g. when parsing arguments.
///
/// [`Client`]: crate::client::Client
/// [`Query`]: crate::query::Query
#[derive(Debug)]
pub enum ClientError {
    /// The database connection stream or parsing arguments has resulted in an error.
    Io(io::Error),
    /// The byte sequence being parsed is not a valid UTF-8 sequence.
    Utf8Parse(FromUtf8Error),
    /// The provided credentials for authorizing are invalid.
    Auth,
    /// The command was processed but failed to get the expected result.
    CommandFailed { message: String },
    /// The query was processed but failed to get the expected result.
    QueryFailed(QueryFailed),
}

impl Display for ClientError {
    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
        match &*self {
            ClientError::Io(ref e) => e.fmt(f),
            ClientError::Utf8Parse(ref e) => e.fmt(f),
            ClientError::Auth => write!(f, "access denied"),
            ClientError::CommandFailed { message } => write!(f, "{}", message),
            ClientError::QueryFailed(q) => write!(f, "{}", q.raw()),
        }
    }
}

impl error::Error for ClientError {}

impl From<io::Error> for ClientError {
    fn from(err: io::Error) -> ClientError {
        ClientError::Io(err)
    }
}

impl From<FromUtf8Error> for ClientError {
    fn from(err: FromUtf8Error) -> ClientError {
        ClientError::Utf8Parse(err)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::io::ErrorKind;

    #[test]
    fn test_io_error_formats_as_debug() {
        let error = ClientError::Io(io::Error::new(ErrorKind::Other, "test"));
        let _ = format!("{:?}", error);
    }

    #[test]
    fn test_io_error_formats_as_empty() {
        let error = ClientError::Io(io::Error::new(ErrorKind::Other, "test"));
        let _ = format!("{}", error);
    }

    #[test]
    fn test_utf8_parse_formats_as_debug() {
        let error = ClientError::Utf8Parse(String::from_utf8(vec![0xa0 as u8, 0xa1]).unwrap_err());
        let _ = format!("{:?}", error);
    }

    #[test]
    fn test_utf8_parse_formats_as_empty() {
        let error = ClientError::Utf8Parse(String::from_utf8(vec![0xa0 as u8, 0xa1]).unwrap_err());
        let _ = format!("{}", error);
    }

    #[test]
    fn test_auth_formats_as_debug() {
        let error = ClientError::Auth;
        let _ = format!("{:?}", error);
    }

    #[test]
    fn test_auth_formats_as_empty() {
        let error = ClientError::Auth;
        let _ = format!("{}", error);
    }

    #[test]
    fn test_command_failed_formats_as_debug() {
        let error = ClientError::CommandFailed {
            message: "error".to_owned(),
        };
        let _ = format!("{:?}", error);
    }

    #[test]
    fn test_command_failed_formats_as_empty() {
        let error = ClientError::CommandFailed {
            message: "error".to_owned(),
        };
        let _ = format!("{}", error);
    }

    #[test]
    fn test_query_failed_formats_as_debug() {
        let error = ClientError::QueryFailed(QueryFailed::new(
            "Stopped at ., 1/1: [XPST0008] Undeclared variable $x.".to_owned(),
        ));
        let _ = format!("{:?}", error);
    }

    #[test]
    fn test_query_failed_formats_as_empty() {
        let error = ClientError::QueryFailed(QueryFailed::new(
            "Stopped at ., 1/1: [XPST0008] Undeclared variable $x.".to_owned(),
        ));
        let _ = format!("{}", error);
    }
}