Input, Driver: Make error messages more idiomatic (#74)

This commit is contained in:
Vilgot Fredenberg
2021-05-21 11:04:12 +02:00
committed by Kyle Simpson
parent 3e0793644f
commit 55e1567b90
5 changed files with 82 additions and 50 deletions

View File

@@ -127,6 +127,7 @@ features = ["v4"]
[dependencies.xsalsa20poly1305] [dependencies.xsalsa20poly1305]
optional = true optional = true
version = "0.7" version = "0.7"
features = ["std"]
[dev-dependencies] [dev-dependencies]
criterion = "0.3" criterion = "0.3"

View File

@@ -6,7 +6,7 @@ use crate::{
}; };
use flume::SendError; use flume::SendError;
use serde_json::Error as JsonError; use serde_json::Error as JsonError;
use std::{error::Error as ErrorTrait, fmt, io::Error as IoError}; use std::{error::Error as StdError, fmt, io::Error as IoError};
use xsalsa20poly1305::aead::Error as CryptoError; use xsalsa20poly1305::aead::Error as CryptoError;
/// Errors encountered while connecting to a Discord voice server over the driver. /// Errors encountered while connecting to a Discord voice server over the driver.
@@ -84,27 +84,43 @@ impl From<WsError> for Error {
impl fmt::Display for Error { impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Failed to connect to Discord RTP server: ")?; write!(f, "failed to connect to Discord RTP server: ")?;
use Error::*; use Error::*;
match self { match self {
AttemptDiscarded => write!(f, "connection attempt was aborted/discarded."), AttemptDiscarded => write!(f, "connection attempt was aborted/discarded"),
Crypto(c) => write!(f, "cryptography error {}.", c), Crypto(e) => e.fmt(f),
CryptoModeInvalid => write!(f, "server changed negotiated encryption mode."), CryptoModeInvalid => write!(f, "server changed negotiated encryption mode"),
CryptoModeUnavailable => write!(f, "server did not offer chosen encryption mode."), CryptoModeUnavailable => write!(f, "server did not offer chosen encryption mode"),
EndpointUrl => write!(f, "endpoint URL received from gateway was invalid."), EndpointUrl => write!(f, "endpoint URL received from gateway was invalid"),
ExpectedHandshake => write!(f, "voice initialisation protocol was violated."), ExpectedHandshake => write!(f, "voice initialisation protocol was violated"),
IllegalDiscoveryResponse => IllegalDiscoveryResponse => write!(f, "IP discovery/NAT punching response was invalid"),
write!(f, "IP discovery/NAT punching response was invalid."), IllegalIp => write!(f, "IP discovery/NAT punching response had bad IP value"),
IllegalIp => write!(f, "IP discovery/NAT punching response had bad IP value."), Io(e) => e.fmt(f),
Io(i) => write!(f, "I/O failure ({}).", i), Json(e) => e.fmt(f),
Json(j) => write!(f, "JSON (de)serialization issue ({}).", j), InterconnectFailure(e) => write!(f, "failed to contact other task ({:?})", e),
InterconnectFailure(r) => write!(f, "failed to contact other task ({:?})", r), Ws(e) => write!(f, "websocket issue ({:?}).", e),
Ws(w) => write!(f, "websocket issue ({:?}).", w),
} }
} }
} }
impl ErrorTrait for Error {} impl StdError for Error {
fn source(&self) -> Option<&(dyn StdError + 'static)> {
match self {
Error::AttemptDiscarded => None,
Error::Crypto(e) => e.source(),
Error::CryptoModeInvalid => None,
Error::CryptoModeUnavailable => None,
Error::EndpointUrl => None,
Error::ExpectedHandshake => None,
Error::IllegalDiscoveryResponse => None,
Error::IllegalIp => None,
Error::Io(e) => e.source(),
Error::Json(e) => e.source(),
Error::InterconnectFailure(_) => None,
Error::Ws(_) => None,
}
}
}
/// Convenience type for Discord voice/driver connection error handling. /// Convenience type for Discord voice/driver connection error handling.
pub type Result<T> = std::result::Result<T, Error>; pub type Result<T> = std::result::Result<T, Error>;

View File

@@ -78,24 +78,39 @@ impl JoinError {
#[cfg(feature = "gateway-core")] #[cfg(feature = "gateway-core")]
impl fmt::Display for JoinError { impl fmt::Display for JoinError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Failed to Join Voice channel: ")?; write!(f, "failed to join voice channel: ")?;
match self { match self {
JoinError::Dropped => write!(f, "request was cancelled/dropped."), JoinError::Dropped => write!(f, "request was cancelled/dropped"),
JoinError::NoSender => write!(f, "no gateway destination."), JoinError::NoSender => write!(f, "no gateway destination"),
JoinError::NoCall => write!(f, "tried to leave a non-existent call."), JoinError::NoCall => write!(f, "tried to leave a non-existent call"),
JoinError::TimedOut => write!(f, "gateway response from Discord timed out."), JoinError::TimedOut => write!(f, "gateway response from Discord timed out"),
#[cfg(feature = "driver-core")] #[cfg(feature = "driver-core")]
JoinError::Driver(t) => write!(f, "internal driver error {}.", t), JoinError::Driver(_) => write!(f, "establishing connection failed"),
#[cfg(feature = "serenity")] #[cfg(feature = "serenity")]
JoinError::Serenity(t) => write!(f, "serenity failure {}.", t), JoinError::Serenity(e) => e.fmt(f),
#[cfg(feature = "twilight")] #[cfg(feature = "twilight")]
JoinError::Twilight(t) => write!(f, "twilight failure {}.", t), JoinError::Twilight(e) => e.fmt(f),
} }
} }
} }
#[cfg(feature = "gateway-core")] #[cfg(feature = "gateway-core")]
impl Error for JoinError {} impl Error for JoinError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
match self {
JoinError::Dropped => None,
JoinError::NoSender => None,
JoinError::NoCall => None,
JoinError::TimedOut => None,
#[cfg(feature = "driver-core")]
JoinError::Driver(e) => Some(e),
#[cfg(feature = "serenity")]
JoinError::Serenity(e) => e.source(),
#[cfg(feature = "twilight")]
JoinError::Twilight(e) => e.source(),
}
}
}
#[cfg(all(feature = "serenity", feature = "gateway-core"))] #[cfg(all(feature = "serenity", feature = "gateway-core"))]
impl From<TrySendError<InterMessage>> for JoinError { impl From<TrySendError<InterMessage>> for JoinError {

View File

@@ -72,20 +72,20 @@ impl From<OpusError> for Error {
impl fmt::Display for Error { impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self { match self {
Error::Dca(e) => write!(f, "{}", e), Error::Dca(_) => write!(f, "opening file DCA failed"),
Error::Io(e) => write!(f, "{}", e), Error::Io(e) => e.fmt(f),
Error::Json { Error::Json {
error, error: _,
parsed_text: _, parsed_text: _,
} => write!(f, "{}", error), } => write!(f, "parsing JSON failed"),
Error::Opus(e) => write!(f, "{}", e), Error::Opus(e) => e.fmt(f),
Error::Metadata => write!(f, "Failed to extract metadata"), Error::Metadata => write!(f, "extracting metadata failed"),
Error::Stdout => write!(f, "Failed to create stdout"), Error::Stdout => write!(f, "creating stdout failed"),
Error::Streams => write!(f, "Error while checking if path is stereo"), Error::Streams => write!(f, "checking if path is stereo failed"),
Error::Streamcatcher(e) => write!(f, "{}", e), Error::Streamcatcher(_) => write!(f, "invalid config for cached input"),
Error::YouTubeDlProcessing(_) => write!(f, "Processing JSON from youtube-dl failed"), Error::YouTubeDlProcessing(_) => write!(f, "youtube-dl returned invalid JSON"),
Error::YouTubeDlRun(_) => write!(f, "youtube-dl encountered an error"), Error::YouTubeDlRun(o) => write!(f, "youtube-dl encontered an error: {:?}", o),
Error::YouTubeDlUrl(_) => write!(f, "Missing url field in JSON"), Error::YouTubeDlUrl(_) => write!(f, "missing youtube-dl url"),
} }
} }
} }
@@ -94,12 +94,12 @@ impl StdError for Error {
fn source(&self) -> Option<&(dyn StdError + 'static)> { fn source(&self) -> Option<&(dyn StdError + 'static)> {
match self { match self {
Error::Dca(e) => Some(e), Error::Dca(e) => Some(e),
Error::Io(e) => Some(e), Error::Io(e) => e.source(),
Error::Json { Error::Json {
error, error,
parsed_text: _, parsed_text: _,
} => Some(error), } => Some(error),
Error::Opus(e) => Some(e), Error::Opus(e) => e.source(),
Error::Metadata => None, Error::Metadata => None,
Error::Stdout => None, Error::Stdout => None,
Error::Streams => None, Error::Streams => None,
@@ -132,11 +132,11 @@ pub enum DcaError {
impl fmt::Display for DcaError { impl fmt::Display for DcaError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self { match self {
DcaError::IoError(e) => write!(f, "{}", e), DcaError::IoError(e) => e.fmt(f),
DcaError::InvalidHeader => write!(f, "Invalid DCA JSON header"), DcaError::InvalidHeader => write!(f, "invalid header"),
DcaError::InvalidMetadata(e) => write!(f, "{}", e), DcaError::InvalidMetadata(_) => write!(f, "invalid metadata"),
DcaError::InvalidSize(e) => write!(f, "Invalid metadata block size: {}", e), DcaError::InvalidSize(e) => write!(f, "invalid metadata block size: {}", e),
DcaError::Opus(e) => write!(f, "{}", e), DcaError::Opus(e) => e.fmt(f),
} }
} }
} }
@@ -144,11 +144,11 @@ impl fmt::Display for DcaError {
impl StdError for DcaError { impl StdError for DcaError {
fn source(&self) -> Option<&(dyn StdError + 'static)> { fn source(&self) -> Option<&(dyn StdError + 'static)> {
match self { match self {
DcaError::IoError(e) => Some(e), DcaError::IoError(e) => e.source(),
DcaError::InvalidHeader => None, DcaError::InvalidHeader => None,
DcaError::InvalidMetadata(e) => Some(e), DcaError::InvalidMetadata(e) => Some(e),
DcaError::InvalidSize(_) => None, DcaError::InvalidSize(_) => None,
DcaError::Opus(e) => Some(e), DcaError::Opus(e) => e.source(),
} }
} }
} }

View File

@@ -21,12 +21,12 @@ pub enum TrackError {
impl fmt::Display for TrackError { impl fmt::Display for TrackError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Failed to operate on track (handle): ")?; write!(f, "failed to operate on track (handle): ")?;
match self { match self {
TrackError::Finished => write!(f, "track ended."), TrackError::Finished => write!(f, "track ended"),
TrackError::InvalidTrackEvent => TrackError::InvalidTrackEvent =>
write!(f, "given event listener can't be fired on a track."), write!(f, "given event listener can't be fired on a track"),
TrackError::SeekUnsupported => write!(f, "track did not support seeking."), TrackError::SeekUnsupported => write!(f, "track did not support seeking"),
} }
} }
} }