use std::io;
use std::str::Utf8Error;
use futures::sync::mpsc::SendError;
use rustc_serialize::{Encodable, Encoder};
use rustc_serialize::json::{Json, ParserError};
use tk_http::Status;
use tk_http::client;
use super::message::{Meta, ValidationError};
quick_error! {
#[derive(Debug)]
pub enum MessageError {
IoError(err: io::Error) {
description(err.description())
display("I/O error: {:?}", err)
from()
}
Utf8Error(err: Utf8Error) {
description(err.description())
display("Decode error {}", err)
from()
}
JsonError(err: ParserError) {
description(err.description())
display("JSON error: {}", err)
from()
}
ValidationError(err: ValidationError) {
description("Message validation error")
display("Validation error: {:?}", err)
from()
}
HttpError(status: Status, body: Option<Json>) {
description("Http error")
display("Http error: {}: {:?}", status.code(), body)
}
Proto(err: client::Error) {
from()
description("Http error")
display("Http error: {}", err)
}
PoolOverflow {
description("too many requests queued")
}
PoolError {
description("error sending message to worker pool")
}
}
}
impl<T> From<SendError<T>> for MessageError {
fn from(_: SendError<T>) -> MessageError {
MessageError::PoolError
}
}
impl Encodable for MessageError {
fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
use self::MessageError::*;
match *self {
HttpError(_, None) => {
s.emit_nil()
}
HttpError(_, Some(ref j)) => {
j.encode(s)
}
Utf8Error(ref err) => {
s.emit_str(format!("{}", err).as_str())
}
JsonError(ref err) => {
s.emit_str(format!("{}", err).as_str())
}
ValidationError(ref err) => {
s.emit_str(format!("{:?}", err).as_str())
}
IoError(ref err) => {
s.emit_str(format!("{:?}", err).as_str())
}
Proto(_) => {
s.emit_str("backend_protocol_error")
}
PoolOverflow => {
s.emit_str("too_many_requests")
}
PoolError => {
s.emit_str("unexpected_pool_error")
}
}
}
}
impl MessageError {
pub fn update_meta(&self, meta: &mut Meta) {
use self::MessageError::*;
let kind = match *self {
HttpError(s, _) => {
meta.insert("http_error".to_string(),
Json::U64(s.code() as u64));
"http_error"
}
IoError(_) | Utf8Error(_) | JsonError(_) => "invalid_content",
Proto(_) | ValidationError(_) => "protocol_error",
PoolError => "unexpected_error",
PoolOverflow => "too_many_requests",
};
meta.insert("error_kind".to_string(), Json::String(kind.to_string()));
}
}