1use std::ffi::NulError;
2use std::fmt;
3
4use crate::Service;
5use bonjour_sys::DNSServiceErrorType;
6use std::error::Error;
7use std::str::Utf8Error;
8use std::sync::PoisonError;
9
10#[derive(Debug)]
13pub enum ZeroconfError {
14 Bonjour(BonjourError),
16 Io(std::io::Error),
18 Timeout(Service),
24 InvalidServiceType(String),
26 InvalidTxtRecord(String),
28 NotFromBrowser(Service),
35 NullString(NulError),
37 Poison,
39 Utf8(Utf8Error),
41 InterfaceNotFound(String),
43 Dropped,
45}
46
47impl From<PoisonError<std::sync::MutexGuard<'_, ()>>> for ZeroconfError {
48 fn from(_: PoisonError<std::sync::MutexGuard<'_, ()>>) -> Self {
49 ZeroconfError::Poison
50 }
51}
52
53impl From<NulError> for ZeroconfError {
54 fn from(s: NulError) -> Self {
55 ZeroconfError::NullString(s)
56 }
57}
58
59impl From<Utf8Error> for ZeroconfError {
60 fn from(s: Utf8Error) -> Self {
61 ZeroconfError::Utf8(s)
62 }
63}
64
65impl From<std::io::Error> for ZeroconfError {
66 fn from(s: std::io::Error) -> Self {
67 ZeroconfError::Io(s)
68 }
69}
70
71impl From<i32> for ZeroconfError {
72 fn from(s: i32) -> Self {
73 ZeroconfError::Bonjour(s.into())
74 }
75}
76
77impl From<BonjourError> for ZeroconfError {
78 fn from(s: BonjourError) -> Self {
79 ZeroconfError::Bonjour(s)
80 }
81}
82
83impl fmt::Display for ZeroconfError {
84 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
85 let s = match self {
86 ZeroconfError::Bonjour(e) => format!("error from bonjour - {}", e),
87 ZeroconfError::Io(e) => e.to_string(),
88 ZeroconfError::Timeout(s) => format!("timeout on {}", s.service_type()),
89 ZeroconfError::InvalidServiceType(s) => format!("invalid service type '{}'", s),
90 ZeroconfError::InvalidTxtRecord(s) => format!("invalid txt record '{}'", s),
91 ZeroconfError::NotFromBrowser(s) => {
92 format!("'{}' service not from browser", s.service_type())
93 }
94 ZeroconfError::NullString(s) => s.to_string(),
95 ZeroconfError::Poison => "mutex was poisoned".to_string(),
96 ZeroconfError::Utf8(e) => e.to_string(),
97 ZeroconfError::InterfaceNotFound(s) => format!("interface not found '{}'", s),
98 ZeroconfError::Dropped => "task dropped before expected".to_string(),
99 };
100 write!(f, "{}", s)
101 }
102}
103
104impl Error for ZeroconfError {
105 fn source(&self) -> Option<&(dyn Error + 'static)> {
106 match self {
107 ZeroconfError::Bonjour(e) => Some(e),
108 ZeroconfError::Io(e) => Some(e),
109 ZeroconfError::NullString(e) => Some(e),
110 ZeroconfError::Utf8(e) => Some(e),
111 _ => None,
112 }
113 }
114}
115
116#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
123pub enum BonjourError {
124 Unknown,
126 NoSuchName,
128 NoMemory,
130 BadParam,
132 BadReference,
134 BadState,
136 BadFlags,
138 Unsupported,
140 NotInitialized,
142 AlreadyRegistered,
144 NameConflict,
146 Invalid,
148 Firewall,
150 Incompatible,
152 BadInterfaceIndex,
154 Refused,
156 NoSuchRecord,
158 NoAuth,
160 NoSuchKey,
162 NATTraversal,
164 DoubleNAT,
166 BadTime,
168 Undefined,
170}
171
172impl fmt::Display for BonjourError {
173 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
174 let s = match self {
175 BonjourError::Unknown => "unknown error",
176 BonjourError::NoSuchName => "no such name",
177 BonjourError::NoMemory => "no memory",
178 BonjourError::BadParam => "bad parameter",
179 BonjourError::BadReference => "bad reference",
180 BonjourError::BadState => "bad state",
181 BonjourError::BadFlags => "bad flags",
182 BonjourError::Unsupported => "unsupported",
183 BonjourError::NotInitialized => "not initialized",
184 BonjourError::AlreadyRegistered => "already registered",
185 BonjourError::NameConflict => "name conflict",
186 BonjourError::Invalid => "invalid",
187 BonjourError::Firewall => "firewall",
188 BonjourError::Incompatible => "incompatible",
189 BonjourError::BadInterfaceIndex => "bad interface index",
190 BonjourError::Refused => "refused",
191 BonjourError::NoSuchRecord => "no such record",
192 BonjourError::NoAuth => "no auth",
193 BonjourError::NoSuchKey => "no such key",
194 BonjourError::NATTraversal => "NAT traversal",
195 BonjourError::DoubleNAT => "double NAT",
196 BonjourError::BadTime => "bad time",
197 BonjourError::Undefined => "undefined error",
198 };
199 write!(f, "{}", s)
200 }
201}
202
203impl std::error::Error for BonjourError {}
204
205impl From<DNSServiceErrorType> for BonjourError {
206 fn from(err: DNSServiceErrorType) -> Self {
207 match err {
208 -65537 => BonjourError::Unknown,
209 -65538 => BonjourError::NoSuchName,
210 -65539 => BonjourError::NoMemory,
211 -65540 => BonjourError::BadParam,
212 -65541 => BonjourError::BadReference,
213 -65542 => BonjourError::BadState,
214 -65543 => BonjourError::BadFlags,
215 -65544 => BonjourError::Unsupported,
216 -65545 => BonjourError::NotInitialized,
217 -65547 => BonjourError::AlreadyRegistered,
218 -65548 => BonjourError::NameConflict,
219 -65549 => BonjourError::Invalid,
220 -65550 => BonjourError::Firewall,
221 -65551 => BonjourError::Incompatible,
222 -65552 => BonjourError::BadInterfaceIndex,
223 -65553 => BonjourError::Refused,
224 -65554 => BonjourError::NoSuchRecord,
225 -65555 => BonjourError::NoAuth,
226 -65556 => BonjourError::NoSuchKey,
227 -65557 => BonjourError::NATTraversal,
228 -65558 => BonjourError::DoubleNAT,
229 -65559 => BonjourError::BadTime,
230 _ => BonjourError::Undefined,
231 }
232 }
233}