use arti_client::DataStream;
use pin_project_lite::pin_project;
use std::io;
use std::pin::Pin;
use std::task::{Context, Poll};
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
#[cfg(all(feature = "native-tls", not(feature = "rustls")))]
use tokio_native_tls::TlsStream as NativeTlsStream;
#[cfg(feature = "rustls")]
use tokio_rustls::client::TlsStream as RustlsStream;
#[cfg(feature = "rustls")]
pin_project! {
#[project = TorStreamProj]
#[allow(missing_docs)]
pub enum TorStream {
Plain {
#[pin]
inner: DataStream,
},
Rustls {
#[pin]
inner: RustlsStream<DataStream>,
},
}
}
#[cfg(all(feature = "native-tls", not(feature = "rustls")))]
pin_project! {
#[project = TorStreamProj]
#[allow(missing_docs)]
pub enum TorStream {
Plain {
#[pin]
inner: DataStream,
},
NativeTls {
#[pin]
inner: NativeTlsStream<DataStream>,
},
}
}
#[cfg(not(any(feature = "native-tls", feature = "rustls")))]
pin_project! {
#[project = TorStreamProj]
#[allow(missing_docs)]
pub enum TorStream {
Plain {
#[pin]
inner: DataStream,
},
}
}
impl TorStream {
pub fn plain(stream: DataStream) -> Self {
Self::Plain { inner: stream }
}
#[cfg(all(feature = "native-tls", not(feature = "rustls")))]
pub fn native_tls(stream: NativeTlsStream<DataStream>) -> Self {
Self::NativeTls { inner: stream }
}
#[cfg(feature = "rustls")]
pub fn rustls(stream: RustlsStream<DataStream>) -> Self {
Self::Rustls { inner: stream }
}
pub fn is_tls(&self) -> bool {
match self {
Self::Plain { .. } => false,
#[cfg(all(feature = "native-tls", not(feature = "rustls")))]
Self::NativeTls { .. } => true,
#[cfg(feature = "rustls")]
Self::Rustls { .. } => true,
}
}
}
impl AsyncRead for TorStream {
fn poll_read(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &mut ReadBuf<'_>,
) -> Poll<io::Result<()>> {
match self.project() {
TorStreamProj::Plain { inner } => inner.poll_read(cx, buf),
#[cfg(all(feature = "native-tls", not(feature = "rustls")))]
TorStreamProj::NativeTls { inner } => inner.poll_read(cx, buf),
#[cfg(feature = "rustls")]
TorStreamProj::Rustls { inner } => inner.poll_read(cx, buf),
}
}
}
impl AsyncWrite for TorStream {
fn poll_write(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &[u8],
) -> Poll<io::Result<usize>> {
match self.project() {
TorStreamProj::Plain { inner } => inner.poll_write(cx, buf),
#[cfg(all(feature = "native-tls", not(feature = "rustls")))]
TorStreamProj::NativeTls { inner } => inner.poll_write(cx, buf),
#[cfg(feature = "rustls")]
TorStreamProj::Rustls { inner } => inner.poll_write(cx, buf),
}
}
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
match self.project() {
TorStreamProj::Plain { inner } => inner.poll_flush(cx),
#[cfg(all(feature = "native-tls", not(feature = "rustls")))]
TorStreamProj::NativeTls { inner } => inner.poll_flush(cx),
#[cfg(feature = "rustls")]
TorStreamProj::Rustls { inner } => inner.poll_flush(cx),
}
}
fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
match self.project() {
TorStreamProj::Plain { inner } => inner.poll_shutdown(cx),
#[cfg(all(feature = "native-tls", not(feature = "rustls")))]
TorStreamProj::NativeTls { inner } => inner.poll_shutdown(cx),
#[cfg(feature = "rustls")]
TorStreamProj::Rustls { inner } => inner.poll_shutdown(cx),
}
}
}