diff --git a/actix-tls/CHANGES.md b/actix-tls/CHANGES.md index 02db1c55..1982b70c 100644 --- a/actix-tls/CHANGES.md +++ b/actix-tls/CHANGES.md @@ -16,6 +16,7 @@ [#429]: https://github.com/actix/actix-net/pull/429 + ## 3.0.0-rc.1 - 2021-11-29 ### Added - Derive `Debug` for `connect::Connection`. [#422] diff --git a/actix-tls/Cargo.toml b/actix-tls/Cargo.toml index 75ea26b0..61bd8bc9 100755 --- a/actix-tls/Cargo.toml +++ b/actix-tls/Cargo.toml @@ -47,7 +47,6 @@ actix-rt = { version = "2.2.0", default-features = false } actix-service = "2.0.0" actix-utils = "3.0.0" -derive_more = "0.99.5" futures-core = { version = "0.3.7", default-features = false, features = ["alloc"] } log = "0.4" pin-project-lite = "0.2.7" diff --git a/actix-tls/src/accept/mod.rs b/actix-tls/src/accept/mod.rs index de220ac5..46710df8 100644 --- a/actix-tls/src/accept/mod.rs +++ b/actix-tls/src/accept/mod.rs @@ -2,11 +2,12 @@ use std::{ convert::Infallible, + error::Error, + fmt, sync::atomic::{AtomicUsize, Ordering}, }; use actix_utils::counter::Counter; -use derive_more::{Display, Error}; #[cfg(feature = "openssl")] #[cfg_attr(docsrs, doc(cfg(feature = "openssl")))] @@ -43,23 +44,45 @@ pub fn max_concurrent_tls_connect(num: usize) { /// TLS handshake error, TLS timeout, or inner service error. /// /// All TLS acceptors from this crate will return the `SvcErr` type parameter as [`Infallible`], -/// which can be cast to your own service type, inferred or otherwise, -/// using [`into_service_error`](Self::into_service_error). -#[derive(Debug, Display, Error)] +/// which can be cast to your own service type, inferred or otherwise, using [`into_service_error`]. +/// +/// [`into_service_error`]: Self::into_service_error +#[derive(Debug)] pub enum TlsError { /// TLS handshake has timed-out. - #[display(fmt = "TLS handshake has timed-out")] Timeout, /// Wraps TLS service errors. - #[display(fmt = "TLS handshake error")] Tls(TlsErr), /// Wraps service errors. - #[display(fmt = "Service error")] Service(SvcErr), } +impl fmt::Display for TlsError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Timeout => f.write_str("TLS handshake has timed-out"), + Self::Tls(_) => f.write_str("TLS handshake error"), + Self::Service(_) => f.write_str("Service error"), + } + } +} + +impl Error for TlsError +where + TlsErr: Error + 'static, + SvcErr: Error + 'static, +{ + fn source(&self) -> Option<&(dyn Error + 'static)> { + match self { + TlsError::Tls(err) => Some(err), + TlsError::Service(err) => Some(err), + TlsError::Timeout => None, + } + } +} + impl TlsError { /// Casts the infallible service error type returned from acceptors into caller's type. /// diff --git a/actix-tls/src/accept/native_tls.rs b/actix-tls/src/accept/native_tls.rs index 9a864a72..b22c1ef2 100644 --- a/actix-tls/src/accept/native_tls.rs +++ b/actix-tls/src/accept/native_tls.rs @@ -20,11 +20,11 @@ use actix_utils::{ counter::Counter, future::{ready, Ready as FutReady}, }; -use derive_more::{Deref, DerefMut, From}; use futures_core::future::LocalBoxFuture; use tokio_native_tls::{native_tls::Error, TlsAcceptor}; use super::{TlsError, DEFAULT_TLS_HANDSHAKE_TIMEOUT, MAX_CONN_COUNTER}; +use crate::impl_more; pub mod reexports { //! Re-exports from `native-tls` that are useful for acceptors. @@ -33,9 +33,12 @@ pub mod reexports { } /// Wraps a `native-tls` based async TLS stream in order to implement [`ActixStream`]. -#[derive(Deref, DerefMut, From)] pub struct TlsStream(tokio_native_tls::TlsStream); +impl_more::from! { tokio_native_tls::TlsStream => TlsStream } +impl_more::deref! { TlsStream => 0: tokio_native_tls::TlsStream } +impl_more::deref_mut! { TlsStream => 0 } + impl AsyncRead for TlsStream { fn poll_read( self: Pin<&mut Self>, diff --git a/actix-tls/src/accept/openssl.rs b/actix-tls/src/accept/openssl.rs index 51a45942..6e65e5fc 100644 --- a/actix-tls/src/accept/openssl.rs +++ b/actix-tls/src/accept/openssl.rs @@ -21,11 +21,11 @@ use actix_utils::{ counter::{Counter, CounterGuard}, future::{ready, Ready as FutReady}, }; -use derive_more::{Deref, DerefMut, From}; use openssl::ssl::{Error, Ssl, SslAcceptor}; use pin_project_lite::pin_project; use super::{TlsError, DEFAULT_TLS_HANDSHAKE_TIMEOUT, MAX_CONN_COUNTER}; +use crate::impl_more; pub mod reexports { //! Re-exports from `openssl` that are useful for acceptors. @@ -36,9 +36,12 @@ pub mod reexports { } /// Wraps an `openssl` based async TLS stream in order to implement [`ActixStream`]. -#[derive(Deref, DerefMut, From)] pub struct TlsStream(tokio_openssl::SslStream); +impl_more::from! { tokio_openssl::SslStream => TlsStream } +impl_more::deref! { TlsStream => 0: tokio_openssl::SslStream } +impl_more::deref_mut! { TlsStream => 0 } + impl AsyncRead for TlsStream { fn poll_read( self: Pin<&mut Self>, diff --git a/actix-tls/src/accept/rustls.rs b/actix-tls/src/accept/rustls.rs index 4eca996e..35fbd34a 100644 --- a/actix-tls/src/accept/rustls.rs +++ b/actix-tls/src/accept/rustls.rs @@ -22,12 +22,12 @@ use actix_utils::{ counter::{Counter, CounterGuard}, future::{ready, Ready as FutReady}, }; -use derive_more::{Deref, DerefMut, From}; use pin_project_lite::pin_project; use tokio_rustls::rustls::ServerConfig; use tokio_rustls::{Accept, TlsAcceptor}; use super::{TlsError, DEFAULT_TLS_HANDSHAKE_TIMEOUT, MAX_CONN_COUNTER}; +use crate::impl_more; pub mod reexports { //! Re-exports from `rustls` that are useful for acceptors. @@ -36,9 +36,12 @@ pub mod reexports { } /// Wraps a `rustls` based async TLS stream in order to implement [`ActixStream`]. -#[derive(Deref, DerefMut, From)] pub struct TlsStream(tokio_rustls::server::TlsStream); +impl_more::from! { tokio_rustls::server::TlsStream => TlsStream } +impl_more::deref! { TlsStream => 0: tokio_rustls::server::TlsStream } +impl_more::deref_mut! { TlsStream => 0 } + impl AsyncRead for TlsStream { fn poll_read( self: Pin<&mut Self>, diff --git a/actix-tls/src/connect/connection.rs b/actix-tls/src/connect/connection.rs index 68972a2a..14c8dc00 100644 --- a/actix-tls/src/connect/connection.rs +++ b/actix-tls/src/connect/connection.rs @@ -1,17 +1,16 @@ -use derive_more::{Deref, DerefMut}; - use super::Host; +use crate::impl_more; /// Wraps underlying I/O and the connection request that initiated it. -#[derive(Debug, Deref, DerefMut)] +#[derive(Debug)] pub struct Connection { pub(crate) req: R, - - #[deref] - #[deref_mut] pub(crate) io: IO, } +impl_more::deref! { Connection => io: IO } +impl_more::deref_mut! { Connection => io } + impl Connection { /// Construct new `Connection` from request and IO parts. pub(crate) fn new(req: R, io: IO) -> Self { diff --git a/actix-tls/src/connect/error.rs b/actix-tls/src/connect/error.rs index 46944988..0452f4c3 100644 --- a/actix-tls/src/connect/error.rs +++ b/actix-tls/src/connect/error.rs @@ -1,30 +1,38 @@ -use std::{error::Error, io}; - -use derive_more::Display; +use std::{error::Error, fmt, io}; /// Errors that can result from using a connector service. -#[derive(Debug, Display)] +#[derive(Debug)] pub enum ConnectError { - /// Failed to resolve the hostname - #[display(fmt = "Failed resolving hostname")] + /// Failed to resolve the hostname. Resolver(Box), - /// No DNS records - #[display(fmt = "No DNS records found for the input")] + /// No DNS records. NoRecords, - /// Invalid input + /// Invalid input. InvalidInput, - /// Unresolved host name - #[display(fmt = "Connector received `Connect` method with unresolved host")] + /// Unresolved host name. Unresolved, - /// Connection IO error - #[display(fmt = "{}", _0)] + /// Connection IO error. Io(io::Error), } +impl fmt::Display for ConnectError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::NoRecords => f.write_str("No DNS records found for the input"), + Self::InvalidInput => f.write_str("Invalid input"), + Self::Unresolved => { + f.write_str("Connector received `Connect` method with unresolved host") + } + Self::Resolver(_) => f.write_str("Failed to resolve hostname"), + Self::Io(_) => f.write_str("I/O error"), + } + } +} + impl Error for ConnectError { fn source(&self) -> Option<&(dyn Error + 'static)> { match self { diff --git a/actix-tls/src/impl_more.rs b/actix-tls/src/impl_more.rs new file mode 100644 index 00000000..c380228b --- /dev/null +++ b/actix-tls/src/impl_more.rs @@ -0,0 +1,40 @@ +/// A helper to implement `Deref` for a type. +#[macro_export] +macro_rules! deref { + ($ty:ident $(<$($generic:ident),*>)? => $field:tt: $target:ty) => { + impl $(<$($generic),*>)? ::core::ops::Deref for $ty $(<$($generic),*>)? { + type Target = $target; + + fn deref(&self) -> &Self::Target { + &self.$field + } + } + }; +} + +/// A helper to implement `DerefMut` for a type. +#[macro_export] +macro_rules! deref_mut { + ($ty:ident $(<$($generic:ident),*>)? => $field:tt) => { + impl $(<$($generic),*>)? ::core::ops::DerefMut for $ty $(<$($generic),*>)? { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.$field + } + } + }; +} + +/// A helper to implement `From` for a unit struct. +#[macro_export] +macro_rules! from { + ($from:ty => $ty:ident $(<$($generic:ident),*>)?) => { + impl $(<$($generic),*>)? ::core::convert::From<$from> for $ty $(<$($generic),*>)? { + fn from(from: $from) -> Self { + Self(from) + } + } + }; +} + +#[allow(unused_imports)] +pub(crate) use crate::{deref, deref_mut, from}; diff --git a/actix-tls/src/lib.rs b/actix-tls/src/lib.rs index 39714dca..dfca00cd 100644 --- a/actix-tls/src/lib.rs +++ b/actix-tls/src/lib.rs @@ -18,3 +18,5 @@ pub mod accept; #[cfg(feature = "connect")] #[cfg_attr(docsrs, doc(cfg(feature = "connect")))] pub mod connect; + +mod impl_more;