use std::error::Error;
use std::net::SocketAddr;
pub enum BrowserError<
#[cfg(any(feature = "tokio", feature = "async-std"))]
SFError: Error = <super::socket::DefaultSocketFactory as super::socket::UdpSocketFactory>::Error,
#[cfg(any(feature = "tokio", feature = "async-std"))]
SError: Error = <<super::socket::DefaultSocketFactory as super::socket::UdpSocketFactory>::Socket as super::socket::UdpSocket>::Error,
#[cfg(all(not(feature = "tokio"), not(feature = "async-std")))]
SFError: Error,
#[cfg(all(not(feature = "tokio"), not(feature = "async-std")))]
SError: Error
> {
BindFailed(SFError),
SetBroadcastFailed(SError),
SendFailed(SocketAddr, SError),
ConnectFailed(SocketAddr, SError),
ReceiveFailed(SError),
InstanceNameTooLong,
ProtocolError(BrowserProtocolError),
}
impl<SFError: std::error::Error, SError: Error> std::fmt::Debug
for BrowserError<SFError, SError>
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
use BrowserError::*;
match self {
BindFailed(e) => write!(f, "BindFailed({:?})", e),
SetBroadcastFailed(e) => write!(f, "SetBroadcastFailed({:?})", e),
SendFailed(addr, e) => write!(f, "SendFailed({:?}, {:?})", addr, e),
ConnectFailed(addr, e) => write!(f, "ConnectFailed({:?}, {:?})", addr, e),
ReceiveFailed(e) => write!(f, "ReceiveFailed({:?})", e),
InstanceNameTooLong => write!(f, "InstanceNameTooLong"),
ProtocolError(e) => write!(f, "ProtocolError({:?})", e),
}
}
}
impl<SFError: std::error::Error, SError: Error> std::fmt::Display
for BrowserError<SFError, SError>
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
use BrowserError::*;
match self {
BindFailed(err) => write!(f, "bind failed: {}", err),
SetBroadcastFailed(err) => write!(f, "enabling broadcast option failed: {}", err),
SendFailed(addr, err) => write!(f, "sending of datagram to '{}' failed: {}", addr, err),
ConnectFailed(addr, err) => write!(f, "connect to '{}' failed: {}", addr, err),
ReceiveFailed(err) => write!(f, "receiving of datagram failed: {}", err),
InstanceNameTooLong => write!(
f,
"specified instance name is longer than {} bytes",
super::MAX_INSTANCE_NAME_LEN
),
ProtocolError(e) => write!(f, "protocol error: {}", e),
}
}
}
impl<SFError: Error, SError: Error> Error for BrowserError<SFError, SError> {
fn cause(&self) -> Option<&dyn Error> {
use BrowserError::*;
match self {
BindFailed(err) => Some(err),
SetBroadcastFailed(err) => Some(err),
SendFailed(_, err) => Some(err),
ConnectFailed(_, err) => Some(err),
ReceiveFailed(err) => Some(err),
InstanceNameTooLong => None,
ProtocolError(err) => Some(err),
}
}
}
#[derive(Debug)]
pub enum BrowserProtocolError {
UnexpectedToken {
expected: BrowserProtocolToken,
found: BrowserProtocolToken,
},
LengthMismatch {
datagram: usize,
header: usize,
},
InvalidUtf8(std::str::Utf8Error),
ExtraneousData(Vec<u8>),
}
impl std::fmt::Display for BrowserProtocolError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
use BrowserProtocolError::*;
match self {
UnexpectedToken { expected, found } => {
write!(f, "expected {}, but found {}", expected, found)
}
LengthMismatch { datagram, header } => write!(
f,
"mismatch between datagram size {} bytes and size specified in header {} bytes",
datagram, header
),
InvalidUtf8(err) => err.fmt(f),
ExtraneousData(data) => write!(f, "{} unexpected trailing bytes", data.len()),
}
}
}
impl Error for BrowserProtocolError {}
#[derive(Debug)]
pub enum BrowserProtocolToken {
EndOfMessage,
Literal(String),
MessageIdentifier(u8),
MessageLength,
DacVersion(u8),
DacPort,
Identifier(BrowserProtocolField),
ValueOf(BrowserProtocolField),
TcpPort,
ViaParameters,
EndpointIdentifierOrSemicolon,
}
impl std::fmt::Display for BrowserProtocolToken {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
use BrowserProtocolToken::*;
match self {
EndOfMessage => write!(f, "end of message"),
Literal(s) => write!(f, "'{}'", s),
MessageIdentifier(v) => write!(f, "message identifier {:#X}", v),
MessageLength => write!(f, "message length"),
DacVersion(v) => write!(f, "dac version {}", v),
DacPort => write!(f, "dac port"),
Identifier(field) => write!(f, "identifier for field {:?}", field),
ValueOf(field) => write!(f, "value for field {:?}", field),
TcpPort => write!(f, "tcp port"),
ViaParameters => write!(f, "via parameters"),
EndpointIdentifierOrSemicolon => write!(f, "endpoint identifier or semicolon"),
}
}
}
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum BrowserProtocolField {
ServerName,
InstanceName,
IsClustered,
Version,
NamedPipeName,
TcpPort,
ViaMachineName,
RpcComputerName,
SpxServiceName,
AppleTalkObjectName,
BvItemName,
BvGroupName,
BvOrgName,
}