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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
use std::error;
use std::ffi::CStr;
use std::fmt;
use std::os::raw::c_int;
use std::result;
use std::str;

use c_ares_sys;

/// Error codes that the library might return.
#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash, PartialOrd, Ord)]
pub enum Error {
    /// DNS server returned answer with no data.
    ENODATA = c_ares_sys::ARES_ENODATA as isize,

    /// DNS server claims query was misformatted.
    EFORMERR = c_ares_sys::ARES_EFORMERR  as isize,

    /// DNS server returned general failure.
    ESERVFAIL = c_ares_sys::ARES_ESERVFAIL as isize,

    /// Domain name not found.
    ENOTFOUND = c_ares_sys::ARES_ENOTFOUND as isize,

    /// DNS server does not implement requested operation.
    ENOTIMP = c_ares_sys::ARES_ENOTIMP as isize,

    /// DNS server refused query.
    EREFUSED = c_ares_sys::ARES_EREFUSED as isize,

    /// Misformatted DNS query.
    EBADQUERY = c_ares_sys::ARES_EBADQUERY as isize,

    /// Misformatted domain name.
    EBADNAME = c_ares_sys::ARES_EBADNAME as isize,

    /// Unsupported address family.
    EBADFAMILY = c_ares_sys::ARES_EBADFAMILY as isize,

    /// Misformatted DNS reply.
    EBADRESP = c_ares_sys::ARES_EBADRESP as isize,

    /// Could not contact DNS servers.
    ECONNREFUSED = c_ares_sys::ARES_ECONNREFUSED as isize,

    /// Timeout while contacting DNS servers.
    ETIMEOUT = c_ares_sys::ARES_ETIMEOUT as isize,

    /// End of file.
    EOF = c_ares_sys::ARES_EOF as isize,

    /// Error reading file.
    EFILE = c_ares_sys::ARES_EFILE as isize,

    /// Out of memory.
    ENOMEM = c_ares_sys::ARES_ENOMEM as isize,

    /// Channel is being destroyed.
    EDESTRUCTION = c_ares_sys::ARES_EDESTRUCTION as isize,

    /// Misformatted string.
    EBADSTR = c_ares_sys::ARES_EBADSTR as isize,

    /// Illegal flags specified.
    EBADFLAGS = c_ares_sys::ARES_EBADFLAGS as isize,

    /// Given hostname is not numeric.
    ENONAME = c_ares_sys::ARES_ENONAME as isize,

    /// Illegal hints flags specified.
    EBADHINTS = c_ares_sys::ARES_EBADHINTS as isize,

    /// c-ares library initialization not yet performed.
    ENOTINITIALIZED = c_ares_sys::ARES_ENOTINITIALIZED as isize,

    /// Error loading iphlpapi.dll.
    ELOADIPHLPAPI = c_ares_sys::ARES_ELOADIPHLPAPI as isize,

    /// Could not find GetNetworkParams function.
    EADDRGETNETWORKPARAMS = c_ares_sys::ARES_EADDRGETNETWORKPARAMS as isize,

    /// DNS query cancelled.
    ECANCELLED = c_ares_sys::ARES_ECANCELLED as isize,

    /// Unknown error.
    UNKNOWN,
}

impl fmt::Display for Error {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> result::Result<(), fmt::Error> {
        let text = match *self {
            Error::ENODATA => "ENODATA",
            Error::EFORMERR => "EFORMERR",
            Error::ESERVFAIL => "ESERVFAIL",
            Error::ENOTFOUND => "ENOTFOUND",
            Error::ENOTIMP => "ENOTIMP",
            Error::EREFUSED => "EREFUSED",
            Error::EBADQUERY => "EBADQUERY",
            Error::EBADNAME => "EBADNAME",
            Error::EBADFAMILY => "EBADFAMILY",
            Error::EBADRESP => "EBADRESP",
            Error::ECONNREFUSED => "ECONNREFUSED",
            Error::ETIMEOUT => "ETIMEOUT",
            Error::EOF => "EOF",
            Error::EFILE => "EFILE",
            Error::ENOMEM => "ENOMEM",
            Error::EDESTRUCTION => "EDESTRUCTION",
            Error::EBADSTR => "EBADSTR",
            Error::EBADFLAGS => "EBADFLAGS",
            Error::ENONAME => "ENONAME",
            Error::EBADHINTS => "EBADHINTS",
            Error::ENOTINITIALIZED => "ENOTINITIALIZED",
            Error::ELOADIPHLPAPI => "ELOADIPHLPAPI",
            Error::EADDRGETNETWORKPARAMS => "EADDRGETNETWORKPARAMS",
            Error::ECANCELLED => "ECANCELLED",
            Error::UNKNOWN => "UNKNOWN",
        };
        fmt.write_str(text)
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        unsafe {
            let ptr = c_ares_sys::ares_strerror(*self as c_int);
            let buf = CStr::from_ptr(ptr).to_bytes();
            str::from_utf8_unchecked(buf)
        }
    }
}

impl From<i32> for Error {
    fn from(code: i32) -> Self {
        match code {
            c_ares_sys::ARES_ENODATA => Error::ENODATA,
            c_ares_sys::ARES_EFORMERR => Error::EFORMERR,
            c_ares_sys::ARES_ESERVFAIL => Error::ESERVFAIL,
            c_ares_sys::ARES_ENOTFOUND => Error::ENOTFOUND,
            c_ares_sys::ARES_ENOTIMP => Error::ENOTIMP,
            c_ares_sys::ARES_EREFUSED => Error::EREFUSED,
            c_ares_sys::ARES_EBADQUERY => Error::EBADQUERY,
            c_ares_sys::ARES_EBADNAME => Error::EBADNAME,
            c_ares_sys::ARES_EBADFAMILY => Error::EBADFAMILY,
            c_ares_sys::ARES_EBADRESP => Error::EBADRESP,
            c_ares_sys::ARES_ECONNREFUSED => Error::ECONNREFUSED,
            c_ares_sys::ARES_ETIMEOUT => Error::ETIMEOUT,
            c_ares_sys::ARES_EOF => Error::EOF,
            c_ares_sys::ARES_EFILE => Error::EFILE,
            c_ares_sys::ARES_ENOMEM => Error::ENOMEM,
            c_ares_sys::ARES_EDESTRUCTION => Error::EDESTRUCTION,
            c_ares_sys::ARES_EBADSTR => Error::EBADSTR,
            c_ares_sys::ARES_EBADFLAGS => Error::EBADFLAGS,
            c_ares_sys::ARES_ENONAME => Error::ENONAME,
            c_ares_sys::ARES_EBADHINTS => Error::EBADHINTS,
            c_ares_sys::ARES_ENOTINITIALIZED => Error::ENOTINITIALIZED,
            c_ares_sys::ARES_ELOADIPHLPAPI => Error::ELOADIPHLPAPI,
            c_ares_sys::ARES_EADDRGETNETWORKPARAMS =>
                Error::EADDRGETNETWORKPARAMS,
            c_ares_sys::ARES_ECANCELLED => Error::ECANCELLED,
            _ => Error::UNKNOWN,
        }
    }
}

/// The type used by this library for methods that might fail.
pub type Result<T> = result::Result<T, Error>;