|
2 | 2 |
|
3 | 3 | use fallible_iterator::FallibleIterator; |
4 | 4 | use postgres_protocol::message::backend::{ErrorFields, ErrorResponseBody}; |
5 | | -use std::convert::From; |
6 | 5 | use std::error; |
7 | 6 | use std::fmt; |
8 | 7 | use std::io; |
| 8 | +use tokio_timer; |
9 | 9 |
|
10 | 10 | pub use self::sqlstate::*; |
11 | 11 |
|
@@ -333,147 +333,175 @@ pub enum ErrorPosition { |
333 | 333 | }, |
334 | 334 | } |
335 | 335 |
|
336 | | -#[doc(hidden)] |
337 | | -pub fn connect(e: Box<error::Error + Sync + Send>) -> Error { |
338 | | - Error(Box::new(ErrorKind::ConnectParams(e))) |
| 336 | +#[derive(Debug, PartialEq)] |
| 337 | +enum Kind { |
| 338 | + Io, |
| 339 | + UnexpectedMessage, |
| 340 | + Tls, |
| 341 | + ToSql, |
| 342 | + FromSql, |
| 343 | + CopyInStream, |
| 344 | + Closed, |
| 345 | + Db, |
| 346 | + Parse, |
| 347 | + Encode, |
| 348 | + MissingUser, |
| 349 | + MissingPassword, |
| 350 | + UnsupportedAuthentication, |
| 351 | + Connect, |
| 352 | + Timer, |
| 353 | + Authentication, |
339 | 354 | } |
340 | 355 |
|
341 | | -#[doc(hidden)] |
342 | | -pub fn tls(e: Box<error::Error + Sync + Send>) -> Error { |
343 | | - Error(Box::new(ErrorKind::Tls(e))) |
| 356 | +struct ErrorInner { |
| 357 | + kind: Kind, |
| 358 | + cause: Option<Box<error::Error + Sync + Send>>, |
344 | 359 | } |
345 | 360 |
|
346 | | -#[doc(hidden)] |
347 | | -pub fn db(e: DbError) -> Error { |
348 | | - Error(Box::new(ErrorKind::Db(e))) |
349 | | -} |
| 361 | +/// An error communicating with the Postgres server. |
| 362 | +pub struct Error(Box<ErrorInner>); |
350 | 363 |
|
351 | | -#[doc(hidden)] |
352 | | -pub fn __db(e: ErrorResponseBody) -> Error { |
353 | | - match DbError::new(&mut e.fields()) { |
354 | | - Ok(e) => Error(Box::new(ErrorKind::Db(e))), |
355 | | - Err(e) => Error(Box::new(ErrorKind::Io(e))), |
| 364 | +impl fmt::Debug for Error { |
| 365 | + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { |
| 366 | + fmt.debug_struct("Error") |
| 367 | + .field("kind", &self.0.kind) |
| 368 | + .field("cause", &self.0.cause) |
| 369 | + .finish() |
356 | 370 | } |
357 | 371 | } |
358 | 372 |
|
359 | | -#[doc(hidden)] |
360 | | -pub fn __user<T>(e: T) -> Error |
361 | | -where |
362 | | - T: Into<Box<error::Error + Sync + Send>>, |
363 | | -{ |
364 | | - Error(Box::new(ErrorKind::Conversion(e.into()))) |
365 | | -} |
366 | | - |
367 | | -#[doc(hidden)] |
368 | | -pub fn io(e: io::Error) -> Error { |
369 | | - Error(Box::new(ErrorKind::Io(e))) |
370 | | -} |
371 | | - |
372 | | -#[doc(hidden)] |
373 | | -pub fn conversion(e: Box<error::Error + Sync + Send>) -> Error { |
374 | | - Error(Box::new(ErrorKind::Conversion(e))) |
375 | | -} |
376 | | - |
377 | | -#[derive(Debug)] |
378 | | -enum ErrorKind { |
379 | | - ConnectParams(Box<error::Error + Sync + Send>), |
380 | | - Tls(Box<error::Error + Sync + Send>), |
381 | | - Db(DbError), |
382 | | - Io(io::Error), |
383 | | - Conversion(Box<error::Error + Sync + Send>), |
384 | | -} |
385 | | - |
386 | | -/// An error communicating with the Postgres server. |
387 | | -#[derive(Debug)] |
388 | | -pub struct Error(Box<ErrorKind>); |
389 | | - |
390 | 373 | impl fmt::Display for Error { |
391 | 374 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { |
392 | 375 | fmt.write_str(error::Error::description(self))?; |
393 | | - match *self.0 { |
394 | | - ErrorKind::ConnectParams(ref err) => write!(fmt, ": {}", err), |
395 | | - ErrorKind::Tls(ref err) => write!(fmt, ": {}", err), |
396 | | - ErrorKind::Db(ref err) => write!(fmt, ": {}", err), |
397 | | - ErrorKind::Io(ref err) => write!(fmt, ": {}", err), |
398 | | - ErrorKind::Conversion(ref err) => write!(fmt, ": {}", err), |
| 376 | + if let Some(ref cause) = self.0.cause { |
| 377 | + write!(fmt, ": {}", cause)?; |
399 | 378 | } |
| 379 | + Ok(()) |
400 | 380 | } |
401 | 381 | } |
402 | 382 |
|
403 | 383 | impl error::Error for Error { |
404 | 384 | fn description(&self) -> &str { |
405 | | - match *self.0 { |
406 | | - ErrorKind::ConnectParams(_) => "invalid connection parameters", |
407 | | - ErrorKind::Tls(_) => "TLS handshake error", |
408 | | - ErrorKind::Db(_) => "database error", |
409 | | - ErrorKind::Io(_) => "IO error", |
410 | | - ErrorKind::Conversion(_) => "type conversion error", |
| 385 | + match self.0.kind { |
| 386 | + Kind::Io => "error communicating with the server", |
| 387 | + Kind::UnexpectedMessage => "unexpected message from server", |
| 388 | + Kind::Tls => "error performing TLS handshake", |
| 389 | + Kind::ToSql => "error serializing a value", |
| 390 | + Kind::FromSql => "error deserializing a value", |
| 391 | + Kind::CopyInStream => "error from a copy_in stream", |
| 392 | + Kind::Closed => "connection closed", |
| 393 | + Kind::Db => "db error", |
| 394 | + Kind::Parse => "error parsing response from server", |
| 395 | + Kind::Encode => "error encoding message to server", |
| 396 | + Kind::MissingUser => "username not provided", |
| 397 | + Kind::MissingPassword => "password not provided", |
| 398 | + Kind::UnsupportedAuthentication => "unsupported authentication method requested", |
| 399 | + Kind::Connect => "error connecting to server", |
| 400 | + Kind::Timer => "timer error", |
| 401 | + Kind::Authentication => "authentication error", |
411 | 402 | } |
412 | 403 | } |
413 | 404 |
|
414 | 405 | fn cause(&self) -> Option<&error::Error> { |
415 | | - match *self.0 { |
416 | | - ErrorKind::ConnectParams(ref err) => Some(&**err), |
417 | | - ErrorKind::Tls(ref err) => Some(&**err), |
418 | | - ErrorKind::Db(ref err) => Some(err), |
419 | | - ErrorKind::Io(ref err) => Some(err), |
420 | | - ErrorKind::Conversion(ref err) => Some(&**err), |
421 | | - } |
| 406 | + self.0.cause.as_ref().map(|e| &**e as &error::Error) |
422 | 407 | } |
423 | 408 | } |
424 | 409 |
|
425 | 410 | impl Error { |
426 | | - /// Returns the SQLSTATE error code associated with this error if it is a DB |
427 | | - /// error. |
| 411 | + /// Returns the error's cause. |
| 412 | + /// |
| 413 | + /// This is the same as `Error::cause` except that it provides extra bounds |
| 414 | + /// required to be able to downcast the error. |
| 415 | + pub fn cause2(&self) -> Option<&(error::Error + 'static + Sync + Send)> { |
| 416 | + self.0.cause.as_ref().map(|e| &**e) |
| 417 | + } |
| 418 | + |
| 419 | + /// Consumes the error, returning its cause. |
| 420 | + pub fn into_cause(self) -> Option<Box<error::Error + Sync + Send>> { |
| 421 | + self.0.cause |
| 422 | + } |
| 423 | + |
| 424 | + /// Returns the SQLSTATE error code associated with the error. |
| 425 | + /// |
| 426 | + /// This is a convenience method that downcasts the cause to a `DbError` |
| 427 | + /// and returns its code. |
428 | 428 | pub fn code(&self) -> Option<&SqlState> { |
429 | | - self.as_db().map(|e| &e.code) |
| 429 | + self.cause2() |
| 430 | + .and_then(|e| e.downcast_ref::<DbError>()) |
| 431 | + .map(|e| e.code()) |
430 | 432 | } |
431 | 433 |
|
432 | | - /// Returns the inner error if this is a connection parameter error. |
433 | | - pub fn as_connection(&self) -> Option<&(error::Error + 'static + Sync + Send)> { |
434 | | - match *self.0 { |
435 | | - ErrorKind::ConnectParams(ref err) => Some(&**err), |
436 | | - _ => None, |
437 | | - } |
| 434 | + fn new(kind: Kind, cause: Option<Box<error::Error + Sync + Send>>) -> Error { |
| 435 | + Error(Box::new(ErrorInner { kind, cause })) |
438 | 436 | } |
439 | 437 |
|
440 | | - /// Returns the `DbError` associated with this error if it is a DB error. |
441 | | - pub fn as_db(&self) -> Option<&DbError> { |
442 | | - match *self.0 { |
443 | | - ErrorKind::Db(ref err) => Some(err), |
444 | | - _ => None, |
445 | | - } |
| 438 | + pub(crate) fn closed() -> Error { |
| 439 | + Error::new(Kind::Closed, None) |
446 | 440 | } |
447 | 441 |
|
448 | | - /// Returns the inner error if this is a conversion error. |
449 | | - pub fn as_conversion(&self) -> Option<&(error::Error + 'static + Sync + Send)> { |
450 | | - match *self.0 { |
451 | | - ErrorKind::Conversion(ref err) => Some(&**err), |
452 | | - _ => None, |
453 | | - } |
| 442 | + pub(crate) fn unexpected_message() -> Error { |
| 443 | + Error::new(Kind::UnexpectedMessage, None) |
454 | 444 | } |
455 | 445 |
|
456 | | - /// Returns the inner `io::Error` associated with this error if it is an IO |
457 | | - /// error. |
458 | | - pub fn as_io(&self) -> Option<&io::Error> { |
459 | | - match *self.0 { |
460 | | - ErrorKind::Io(ref err) => Some(err), |
461 | | - _ => None, |
| 446 | + pub(crate) fn db(error: ErrorResponseBody) -> Error { |
| 447 | + match DbError::new(&mut error.fields()) { |
| 448 | + Ok(e) => Error::new(Kind::Db, Some(Box::new(e))), |
| 449 | + Err(e) => Error::new(Kind::Parse, Some(Box::new(e))), |
462 | 450 | } |
463 | 451 | } |
464 | | -} |
465 | 452 |
|
466 | | -impl From<io::Error> for Error { |
467 | | - fn from(err: io::Error) -> Error { |
468 | | - Error(Box::new(ErrorKind::Io(err))) |
| 453 | + pub(crate) fn parse(e: io::Error) -> Error { |
| 454 | + Error::new(Kind::Parse, Some(Box::new(e))) |
469 | 455 | } |
470 | | -} |
471 | 456 |
|
472 | | -impl From<Error> for io::Error { |
473 | | - fn from(err: Error) -> io::Error { |
474 | | - match *err.0 { |
475 | | - ErrorKind::Io(e) => e, |
476 | | - _ => io::Error::new(io::ErrorKind::Other, err), |
477 | | - } |
| 457 | + pub(crate) fn encode(e: io::Error) -> Error { |
| 458 | + Error::new(Kind::Encode, Some(Box::new(e))) |
| 459 | + } |
| 460 | + |
| 461 | + pub(crate) fn to_sql(e: Box<error::Error + Sync + Send>) -> Error { |
| 462 | + Error::new(Kind::ToSql, Some(e)) |
| 463 | + } |
| 464 | + |
| 465 | + pub(crate) fn from_sql(e: Box<error::Error + Sync + Send>) -> Error { |
| 466 | + Error::new(Kind::FromSql, Some(e)) |
| 467 | + } |
| 468 | + |
| 469 | + pub(crate) fn copy_in_stream<E>(e: E) -> Error |
| 470 | + where |
| 471 | + E: Into<Box<error::Error + Sync + Send>>, |
| 472 | + { |
| 473 | + Error::new(Kind::CopyInStream, Some(e.into())) |
| 474 | + } |
| 475 | + |
| 476 | + pub(crate) fn missing_user() -> Error { |
| 477 | + Error::new(Kind::MissingUser, None) |
| 478 | + } |
| 479 | + |
| 480 | + pub(crate) fn missing_password() -> Error { |
| 481 | + Error::new(Kind::MissingPassword, None) |
| 482 | + } |
| 483 | + |
| 484 | + pub(crate) fn unsupported_authentication() -> Error { |
| 485 | + Error::new(Kind::UnsupportedAuthentication, None) |
| 486 | + } |
| 487 | + |
| 488 | + pub(crate) fn tls(e: Box<error::Error + Sync + Send>) -> Error { |
| 489 | + Error::new(Kind::Tls, Some(e)) |
| 490 | + } |
| 491 | + |
| 492 | + pub(crate) fn connect(e: io::Error) -> Error { |
| 493 | + Error::new(Kind::Connect, Some(Box::new(e))) |
| 494 | + } |
| 495 | + |
| 496 | + pub(crate) fn timer(e: tokio_timer::Error) -> Error { |
| 497 | + Error::new(Kind::Timer, Some(Box::new(e))) |
| 498 | + } |
| 499 | + |
| 500 | + pub(crate) fn io(e: io::Error) -> Error { |
| 501 | + Error::new(Kind::Io, Some(Box::new(e))) |
| 502 | + } |
| 503 | + |
| 504 | + pub(crate) fn authentication(e: io::Error) -> Error { |
| 505 | + Error::new(Kind::Authentication, Some(Box::new(e))) |
478 | 506 | } |
479 | 507 | } |
0 commit comments