diff --git a/Cargo.toml b/Cargo.toml index c6ebd9eae..395111155 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -127,6 +127,7 @@ features = ["v4"] [dependencies.xsalsa20poly1305] optional = true version = "0.7" +features = ["std"] [dev-dependencies] criterion = "0.3" diff --git a/src/driver/connection/error.rs b/src/driver/connection/error.rs index c3995e84a..d7f323698 100644 --- a/src/driver/connection/error.rs +++ b/src/driver/connection/error.rs @@ -6,7 +6,7 @@ use crate::{ }; use flume::SendError; 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; /// Errors encountered while connecting to a Discord voice server over the driver. @@ -84,27 +84,43 @@ impl From for Error { impl fmt::Display for Error { 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::*; match self { - AttemptDiscarded => write!(f, "connection attempt was aborted/discarded."), - Crypto(c) => write!(f, "cryptography error {}.", c), - CryptoModeInvalid => write!(f, "server changed negotiated encryption mode."), - CryptoModeUnavailable => write!(f, "server did not offer chosen encryption mode."), - EndpointUrl => write!(f, "endpoint URL received from gateway was invalid."), - ExpectedHandshake => write!(f, "voice initialisation protocol was violated."), - IllegalDiscoveryResponse => - write!(f, "IP discovery/NAT punching response was invalid."), - IllegalIp => write!(f, "IP discovery/NAT punching response had bad IP value."), - Io(i) => write!(f, "I/O failure ({}).", i), - Json(j) => write!(f, "JSON (de)serialization issue ({}).", j), - InterconnectFailure(r) => write!(f, "failed to contact other task ({:?})", r), - Ws(w) => write!(f, "websocket issue ({:?}).", w), + AttemptDiscarded => write!(f, "connection attempt was aborted/discarded"), + Crypto(e) => e.fmt(f), + CryptoModeInvalid => write!(f, "server changed negotiated encryption mode"), + CryptoModeUnavailable => write!(f, "server did not offer chosen encryption mode"), + EndpointUrl => write!(f, "endpoint URL received from gateway was invalid"), + ExpectedHandshake => write!(f, "voice initialisation protocol was violated"), + IllegalDiscoveryResponse => write!(f, "IP discovery/NAT punching response was invalid"), + IllegalIp => write!(f, "IP discovery/NAT punching response had bad IP value"), + Io(e) => e.fmt(f), + Json(e) => e.fmt(f), + InterconnectFailure(e) => write!(f, "failed to contact other task ({:?})", e), + Ws(e) => write!(f, "websocket issue ({:?}).", e), } } } -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. pub type Result = std::result::Result; diff --git a/src/error.rs b/src/error.rs index f3a05ecd3..25731eeaf 100644 --- a/src/error.rs +++ b/src/error.rs @@ -78,24 +78,39 @@ impl JoinError { #[cfg(feature = "gateway-core")] impl fmt::Display for JoinError { 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 { - JoinError::Dropped => write!(f, "request was cancelled/dropped."), - JoinError::NoSender => write!(f, "no gateway destination."), - JoinError::NoCall => write!(f, "tried to leave a non-existent call."), - JoinError::TimedOut => write!(f, "gateway response from Discord timed out."), + JoinError::Dropped => write!(f, "request was cancelled/dropped"), + JoinError::NoSender => write!(f, "no gateway destination"), + JoinError::NoCall => write!(f, "tried to leave a non-existent call"), + JoinError::TimedOut => write!(f, "gateway response from Discord timed out"), #[cfg(feature = "driver-core")] - JoinError::Driver(t) => write!(f, "internal driver error {}.", t), + JoinError::Driver(_) => write!(f, "establishing connection failed"), #[cfg(feature = "serenity")] - JoinError::Serenity(t) => write!(f, "serenity failure {}.", t), + JoinError::Serenity(e) => e.fmt(f), #[cfg(feature = "twilight")] - JoinError::Twilight(t) => write!(f, "twilight failure {}.", t), + JoinError::Twilight(e) => e.fmt(f), } } } #[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"))] impl From> for JoinError { diff --git a/src/input/error.rs b/src/input/error.rs index 01682e81b..551ea3695 100644 --- a/src/input/error.rs +++ b/src/input/error.rs @@ -72,20 +72,20 @@ impl From for Error { impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - Error::Dca(e) => write!(f, "{}", e), - Error::Io(e) => write!(f, "{}", e), + Error::Dca(_) => write!(f, "opening file DCA failed"), + Error::Io(e) => e.fmt(f), Error::Json { - error, + error: _, parsed_text: _, - } => write!(f, "{}", error), - Error::Opus(e) => write!(f, "{}", e), - Error::Metadata => write!(f, "Failed to extract metadata"), - Error::Stdout => write!(f, "Failed to create stdout"), - Error::Streams => write!(f, "Error while checking if path is stereo"), - Error::Streamcatcher(e) => write!(f, "{}", e), - Error::YouTubeDlProcessing(_) => write!(f, "Processing JSON from youtube-dl failed"), - Error::YouTubeDlRun(_) => write!(f, "youtube-dl encountered an error"), - Error::YouTubeDlUrl(_) => write!(f, "Missing url field in JSON"), + } => write!(f, "parsing JSON failed"), + Error::Opus(e) => e.fmt(f), + Error::Metadata => write!(f, "extracting metadata failed"), + Error::Stdout => write!(f, "creating stdout failed"), + Error::Streams => write!(f, "checking if path is stereo failed"), + Error::Streamcatcher(_) => write!(f, "invalid config for cached input"), + Error::YouTubeDlProcessing(_) => write!(f, "youtube-dl returned invalid JSON"), + Error::YouTubeDlRun(o) => write!(f, "youtube-dl encontered an error: {:?}", o), + Error::YouTubeDlUrl(_) => write!(f, "missing youtube-dl url"), } } } @@ -94,12 +94,12 @@ impl StdError for Error { fn source(&self) -> Option<&(dyn StdError + 'static)> { match self { Error::Dca(e) => Some(e), - Error::Io(e) => Some(e), + Error::Io(e) => e.source(), Error::Json { error, parsed_text: _, } => Some(error), - Error::Opus(e) => Some(e), + Error::Opus(e) => e.source(), Error::Metadata => None, Error::Stdout => None, Error::Streams => None, @@ -132,11 +132,11 @@ pub enum DcaError { impl fmt::Display for DcaError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - DcaError::IoError(e) => write!(f, "{}", e), - DcaError::InvalidHeader => write!(f, "Invalid DCA JSON header"), - DcaError::InvalidMetadata(e) => write!(f, "{}", e), - DcaError::InvalidSize(e) => write!(f, "Invalid metadata block size: {}", e), - DcaError::Opus(e) => write!(f, "{}", e), + DcaError::IoError(e) => e.fmt(f), + DcaError::InvalidHeader => write!(f, "invalid header"), + DcaError::InvalidMetadata(_) => write!(f, "invalid metadata"), + DcaError::InvalidSize(e) => write!(f, "invalid metadata block size: {}", e), + DcaError::Opus(e) => e.fmt(f), } } } @@ -144,11 +144,11 @@ impl fmt::Display for DcaError { impl StdError for DcaError { fn source(&self) -> Option<&(dyn StdError + 'static)> { match self { - DcaError::IoError(e) => Some(e), + DcaError::IoError(e) => e.source(), DcaError::InvalidHeader => None, DcaError::InvalidMetadata(e) => Some(e), DcaError::InvalidSize(_) => None, - DcaError::Opus(e) => Some(e), + DcaError::Opus(e) => e.source(), } } } diff --git a/src/tracks/error.rs b/src/tracks/error.rs index e66863030..1acada94e 100644 --- a/src/tracks/error.rs +++ b/src/tracks/error.rs @@ -21,12 +21,12 @@ pub enum TrackError { impl fmt::Display for TrackError { 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 { - TrackError::Finished => write!(f, "track ended."), + TrackError::Finished => write!(f, "track ended"), TrackError::InvalidTrackEvent => - write!(f, "given event listener can't be fired on a track."), - TrackError::SeekUnsupported => write!(f, "track did not support seeking."), + write!(f, "given event listener can't be fired on a track"), + TrackError::SeekUnsupported => write!(f, "track did not support seeking"), } } }