abstract_ns/
error.rs

1use std::error::{Error as StdError};
2use std::io::{Error as IoError, ErrorKind as IoErrorKind};
3
4use void::{unreachable, Void};
5
6
7quick_error! {
8    /// A generic name resolution error
9    ///
10    /// It's designed to provide basic abstraction over error types and also
11    /// provide as much information as possible by carrying original error
12    #[derive(Debug)]
13    pub enum Error {
14        /// Couldn't parse a name before resolution
15        ///
16        /// It's expected that this error is permanent and is a failure of
17        /// validating user input or the name in the configuration is invalid,
18        /// but it's possible that some resolver have very specific
19        /// requirements for names, so you might want to change resolver too.
20        InvalidName(name: String, description: &'static str) {
21            description("name that you are trying to resolve is invalid")
22            display("name {:?} is invalid: {}", name, description)
23        }
24        /// Temporary name resolution error
25        ///
26        /// This means either name server returned this kind of error or
27        /// we couldn't connect to a name server itself. It's safe to assume
28        /// that you can retry name resolution in a moment
29        TemporaryError(err: Box<StdError + Send + Sync>) {
30            description("temporary name resolution error")
31            display("temporary name resolution error: {}", err)
32            cause(&**err)
33        }
34        /// We have sucessfully done name resolution but there is no such name
35        NameNotFound {
36            description("name not found")
37            display("name not found")
38        }
39        /// The target resolver can only resolve host names and no default
40        /// port is specified
41        NoDefaultPort {
42            description("the resolver can only resolve hostname to an IP, \
43                address, so port must be specified to get full address")
44        }
45    }
46}
47
48impl Error {
49    /// Wraps the error into `std::io::Error`.
50    pub fn into_io(self) -> IoError {
51        match self {
52            Error::InvalidName(_, _) =>
53                IoError::new(IoErrorKind::InvalidInput, self),
54            Error::TemporaryError(_) =>
55                IoError::new(IoErrorKind::Other, self),
56            Error::NameNotFound =>
57                IoError::new(IoErrorKind::NotFound, self),
58            Error::NoDefaultPort =>
59                IoError::new(IoErrorKind::NotFound, self),
60        }
61    }
62}
63
64impl From<Void> for Error {
65    fn from(v: Void) -> Error {
66        unreachable(v);
67    }
68}
69
70#[test]
71fn send_sync() {
72    fn send_sync<T: Send+Sync>(_: T) {}
73    send_sync(Error::NameNotFound);
74}
75
76#[test]
77fn wrap_into_io() {
78    assert_eq!(Error::InvalidName("foo".to_string(), "bar").into_io().kind(),
79        IoErrorKind::InvalidInput);
80    assert_eq!(Error::TemporaryError(Box::new(IoError::new(IoErrorKind::Other, "oh no!"))).into_io().kind(),
81        IoErrorKind::Other);
82    assert_eq!(Error::NameNotFound.into_io().kind(),
83        IoErrorKind::NotFound);
84}