async_dnssd/
error.rs

1use std::{
2	error,
3	fmt,
4	io,
5};
6
7use crate::ffi;
8
9/// API Error
10pub enum Error {
11	/// If error code used some recognized name
12	KnownError(ffi::DNSServiceError),
13	/// Unrecognized error codes
14	UnknownError(i32),
15	/// IO error
16	IoError(io::Error),
17}
18
19impl Error {
20	/// Check if a raw error code represents an error, and convert it
21	/// accordingly.  (Not all codes are treated as an error, including
22	/// `0`).
23	pub fn from(value: ffi::DNSServiceErrorType) -> Result<(), Self> {
24		if ffi::DNSServiceNoError::try_from(value).is_some() {
25			Ok(())
26		} else {
27			match ffi::DNSServiceError::try_from(value) {
28				Some(e) => Err(Self::KnownError(e)),
29				None => Err(Self::UnknownError(value)),
30			}
31		}
32	}
33}
34
35impl From<io::Error> for Error {
36	fn from(e: io::Error) -> Self {
37		Self::IoError(e)
38	}
39}
40
41impl From<Error> for io::Error {
42	fn from(e: Error) -> Self {
43		match e {
44			Error::IoError(e) => e,
45			e => Self::other(e),
46		}
47	}
48}
49
50impl fmt::Debug for Error {
51	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
52		match self {
53			Self::KnownError(ffi_err) => write!(f, "known error {:?}: {}", ffi_err, ffi_err),
54			Self::UnknownError(e) => write!(f, "unknown error code: {:?}", e),
55			Self::IoError(e) => write!(f, "io error: {:?}", e),
56		}
57	}
58}
59impl fmt::Display for Error {
60	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
61		match self {
62			Self::KnownError(ffi_err) => write!(f, "{}", ffi_err),
63			Self::UnknownError(e) => write!(f, "unknown error code: {:?}", e),
64			Self::IoError(e) => write!(f, "io error: {}", e),
65		}
66	}
67}
68impl error::Error for Error {
69	fn source(&self) -> Option<&(dyn error::Error + 'static)> {
70		match self {
71			Self::KnownError(ffi_err) => Some(ffi_err),
72			Self::UnknownError(_) => None,
73			Self::IoError(e) => Some(e),
74		}
75	}
76}
77
78impl ffi::DNSServiceError {
79	pub fn description(&self) -> &str {
80		use ffi::DNSServiceError::*;
81		match *self {
82			Unknown => "unknown error",
83			NoSuchName => "no such name",
84			NoMemory => "out of memory",
85			BadParam => "bad parameter",
86			BadReference => "bad reference",
87			BadState => "bad state",
88			BadFlags => "bad flags",
89			Unsupported => "not supported",
90			NotInitialized => "not initialized",
91			// NoCache => "no cache",
92			AlreadyRegistered => "already registered",
93			NameConflict => "name conflict",
94			Invalid => "invalid",
95			Firewall => "firewall",
96			Incompatible => "client library incompatible with daemon",
97			BadInterfaceIndex => "bad interface index",
98			Refused => "refused",
99			NoSuchRecord => "no such record",
100			NoAuth => "no auth",
101			NoSuchKey => "no such key",
102			NATTraversal => "NAT traversal",
103			DoubleNAT => "double NAT",
104			BadTime => "bad time",
105			BadSig => "bad signature",
106			BadKey => "bad key",
107			Transient => "transient",
108			ServiceNotRunning => "service not running",
109			NATPortMappingUnsupported => "NAT port mapping unsupported",
110			NATPortMappingDisabled => "NAT port mapping disabled",
111			NoRouter => "no router",
112			PollingMode => "polling mode",
113			Timeout => "timeout",
114			DefunctConnection => "defunct connection",
115			PolicyDenied => "policy denied",
116			NotPermitted => "not permitted",
117			StaleData => "stale data",
118		}
119	}
120}
121
122impl fmt::Display for ffi::DNSServiceError {
123	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
124		write!(f, "{}", self.description())
125	}
126}
127impl error::Error for ffi::DNSServiceError {
128	fn description(&self) -> &str {
129		self.description()
130	}
131}
132
133#[cfg(test)]
134mod tests {
135	use super::*;
136
137	#[test]
138	#[allow(deprecated)]
139	fn test_ffi_err_description() {
140		// make sure Error::description still works, although we now provide a
141		// (non-trait) description method
142		assert_eq!(
143			error::Error::description(&ffi::DNSServiceError::NoAuth),
144			"no auth"
145		);
146	}
147}