1use std::error::Error;
2use std::net::SocketAddr;
3
4pub enum BrowserError<
6 #[cfg(any(feature = "tokio", feature = "async-std"))]
7 SFError: Error = <super::socket::DefaultSocketFactory as super::socket::UdpSocketFactory>::Error,
8 #[cfg(any(feature = "tokio", feature = "async-std"))]
9 SError: Error = <<super::socket::DefaultSocketFactory as super::socket::UdpSocketFactory>::Socket as super::socket::UdpSocket>::Error,
10 #[cfg(all(not(feature = "tokio"), not(feature = "async-std")))]
11 SFError: Error,
12 #[cfg(all(not(feature = "tokio"), not(feature = "async-std")))]
13 SError: Error
14> {
15 BindFailed(SFError),
17
18 SetBroadcastFailed(SError),
20
21 SendFailed(SocketAddr, SError),
23
24 ConnectFailed(SocketAddr, SError),
26
27 ReceiveFailed(SError),
29
30 InstanceNameTooLong,
32
33 ProtocolError(BrowserProtocolError),
35}
36
37impl<SFError: std::error::Error, SError: Error> std::fmt::Debug
39 for BrowserError<SFError, SError>
40{
41 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
42 use BrowserError::*;
43
44 match self {
45 BindFailed(e) => write!(f, "BindFailed({:?})", e),
46 SetBroadcastFailed(e) => write!(f, "SetBroadcastFailed({:?})", e),
47 SendFailed(addr, e) => write!(f, "SendFailed({:?}, {:?})", addr, e),
48 ConnectFailed(addr, e) => write!(f, "ConnectFailed({:?}, {:?})", addr, e),
49 ReceiveFailed(e) => write!(f, "ReceiveFailed({:?})", e),
50 InstanceNameTooLong => write!(f, "InstanceNameTooLong"),
51 ProtocolError(e) => write!(f, "ProtocolError({:?})", e),
52 }
53 }
54}
55
56impl<SFError: std::error::Error, SError: Error> std::fmt::Display
57 for BrowserError<SFError, SError>
58{
59 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
60 use BrowserError::*;
61
62 match self {
63 BindFailed(err) => write!(f, "bind failed: {}", err),
64 SetBroadcastFailed(err) => write!(f, "enabling broadcast option failed: {}", err),
65 SendFailed(addr, err) => write!(f, "sending of datagram to '{}' failed: {}", addr, err),
66 ConnectFailed(addr, err) => write!(f, "connect to '{}' failed: {}", addr, err),
67 ReceiveFailed(err) => write!(f, "receiving of datagram failed: {}", err),
68 InstanceNameTooLong => write!(
69 f,
70 "specified instance name is longer than {} bytes",
71 super::MAX_INSTANCE_NAME_LEN
72 ),
73 ProtocolError(e) => write!(f, "protocol error: {}", e),
74 }
75 }
76}
77
78impl<SFError: Error, SError: Error> Error for BrowserError<SFError, SError> {
79 fn cause(&self) -> Option<&dyn Error> {
80 use BrowserError::*;
81
82 match self {
83 BindFailed(err) => Some(err),
84 SetBroadcastFailed(err) => Some(err),
85 SendFailed(_, err) => Some(err),
86 ConnectFailed(_, err) => Some(err),
87 ReceiveFailed(err) => Some(err),
88 InstanceNameTooLong => None,
89 ProtocolError(err) => Some(err),
90 }
91 }
92}
93
94#[derive(Debug)]
96pub enum BrowserProtocolError {
97 UnexpectedToken {
99 expected: BrowserProtocolToken,
101
102 found: BrowserProtocolToken,
104 },
105
106 LengthMismatch {
109 datagram: usize,
111
112 header: usize,
114 },
115
116 InvalidUtf8(std::str::Utf8Error),
118
119 ExtraneousData(Vec<u8>),
121}
122
123impl std::fmt::Display for BrowserProtocolError {
124 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
125 use BrowserProtocolError::*;
126
127 match self {
128 UnexpectedToken { expected, found } => {
129 write!(f, "expected {}, but found {}", expected, found)
130 }
131 LengthMismatch { datagram, header } => write!(
132 f,
133 "mismatch between datagram size {} bytes and size specified in header {} bytes",
134 datagram, header
135 ),
136 InvalidUtf8(err) => err.fmt(f),
137 ExtraneousData(data) => write!(f, "{} unexpected trailing bytes", data.len()),
138 }
139 }
140}
141
142impl Error for BrowserProtocolError {}
143
144#[derive(Debug)]
146pub enum BrowserProtocolToken {
147 EndOfMessage,
149
150 Literal(String),
152
153 MessageIdentifier(u8),
155
156 MessageLength,
158
159 DacVersion(u8),
160 DacPort,
161 Identifier(BrowserProtocolField),
162 ValueOf(BrowserProtocolField),
163 TcpPort,
164 ViaParameters,
165 EndpointIdentifierOrSemicolon,
166}
167
168impl std::fmt::Display for BrowserProtocolToken {
169 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
170 use BrowserProtocolToken::*;
171
172 match self {
173 EndOfMessage => write!(f, "end of message"),
174 Literal(s) => write!(f, "'{}'", s),
175 MessageIdentifier(v) => write!(f, "message identifier {:#X}", v),
176 MessageLength => write!(f, "message length"),
177 DacVersion(v) => write!(f, "dac version {}", v),
178 DacPort => write!(f, "dac port"),
179 Identifier(field) => write!(f, "identifier for field {:?}", field),
180 ValueOf(field) => write!(f, "value for field {:?}", field),
181 TcpPort => write!(f, "tcp port"),
182 ViaParameters => write!(f, "via parameters"),
183 EndpointIdentifierOrSemicolon => write!(f, "endpoint identifier or semicolon"),
184 }
185 }
186}
187
188#[derive(Debug, PartialEq, Eq, Copy, Clone)]
190pub enum BrowserProtocolField {
191 ServerName,
192 InstanceName,
193 IsClustered,
194 Version,
195
196 NamedPipeName,
197 TcpPort,
198 ViaMachineName,
199 RpcComputerName,
200 SpxServiceName,
201 AppleTalkObjectName,
202 BvItemName,
203 BvGroupName,
204 BvOrgName,
205}