use std::convert::From;
use std::error::Error as StdError;
use std::fmt::{Display, Error as FmtError, Formatter};
use http::uri::InvalidUri;
use hyper::{Error as HttpError, StatusCode};
#[cfg(feature = "tls")]
use native_tls::Error as TlsError;
use serde_derive::{Deserialize, Serialize};
use serde_json::Error as SerializationError;
use tokio::timer::timeout::Error as TokioTimeoutError;
use url::ParseError as UrlError;
#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
pub struct ApiError {
pub cause: Option<String>,
#[serde(rename = "errorCode")]
pub error_code: u64,
pub index: u64,
pub message: String,
}
impl Display for ApiError {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
write!(f, "{}", self.message)
}
}
impl StdError for ApiError {
fn description(&self) -> &str {
&self.message
}
}
#[derive(Debug)]
pub enum Error {
Api(ApiError),
Http(HttpError),
InvalidConditions,
InvalidUri(InvalidUri),
InvalidUrl(UrlError),
NoEndpoints,
Serialization(SerializationError),
#[cfg(feature = "tls")]
Tls(TlsError),
UnexpectedStatus(StatusCode),
}
impl Display for Error {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
match *self {
Error::Api(ref error) => write!(f, "{}", error),
Error::Http(ref error) => write!(f, "{}", error),
ref error @ Error::InvalidConditions => write!(f, "{}", error.description()),
Error::InvalidUri(ref error) => write!(f, "{}", error),
Error::InvalidUrl(ref error) => write!(f, "{}", error),
ref error @ Error::NoEndpoints => write!(f, "{}", error.description()),
#[cfg(feature = "tls")]
Error::Tls(ref error) => write!(f, "{}", error),
Error::Serialization(ref error) => write!(f, "{}", error),
Error::UnexpectedStatus(ref status) => write!(
f,
"the etcd server returned an unexpected HTTP status code: {}",
status
),
}
}
}
impl StdError for Error {
fn description(&self) -> &str {
match *self {
Error::Api(_) => "the etcd server returned an error",
Error::Http(_) => "an error occurred during the HTTP request",
Error::InvalidConditions => "current value or modified index is required",
Error::InvalidUri(_) => "a supplied endpoint could not be parsed as a URI",
Error::InvalidUrl(_) => "a URL for the request could not be generated",
Error::NoEndpoints => "at least one endpoint is required to create a Client",
#[cfg(feature = "tls")]
Error::Tls(_) => "an error occurred configuring TLS",
Error::Serialization(_) => "an error occurred deserializing JSON",
Error::UnexpectedStatus(_) => "the etcd server returned an unexpected HTTP status code",
}
}
}
impl From<HttpError> for Error {
fn from(error: HttpError) -> Error {
Error::Http(error)
}
}
#[cfg(feature = "tls")]
impl From<TlsError> for Error {
fn from(error: TlsError) -> Error {
Error::Tls(error)
}
}
impl From<UrlError> for Error {
fn from(error: UrlError) -> Error {
Error::InvalidUrl(error)
}
}
impl From<SerializationError> for Error {
fn from(error: SerializationError) -> Error {
Error::Serialization(error)
}
}
impl From<InvalidUri> for Error {
fn from(error: InvalidUri) -> Error {
Error::InvalidUri(error)
}
}
#[derive(Debug)]
pub enum WatchError {
Other(Vec<Error>),
Timeout,
}
impl<T> From<TokioTimeoutError<T>> for WatchError {
fn from(_: TokioTimeoutError<T>) -> Self {
WatchError::Timeout
}
}
impl Display for WatchError {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
match *self {
WatchError::Timeout => write!(f, "{}", self.description()),
ref other => other.fmt(f),
}
}
}
impl StdError for WatchError {
fn description(&self) -> &str {
"operation timed out"
}
}