//! Declare a macro for making opaque runtime wrappers. /// Implement delegating implementations of the runtime traits for a type $t /// whose member $r implements Runtime. Used to hide the details of the /// implementation of $t. #[allow(unused)] // Can be unused if no runtimes are declared. macro_rules! implement_opaque_runtime { { $t:ty { $member:ident : $mty:ty } } => { impl futures::task::Spawn for $t { // `track_caller` required for tokio-console #[inline] #[track_caller] fn spawn_obj(&self, future: futures::future::FutureObj<'static, ()>) -> Result<(), futures::task::SpawnError> { self.$member.spawn_obj(future) } } impl $crate::traits::Blocking for $t { type ThreadHandle = <$mty as $crate::traits::Blocking>::ThreadHandle; // `track_caller` required for tokio-console #[inline] #[track_caller] fn spawn_blocking(&self, f: F) -> <$mty as $crate::traits::Blocking>::ThreadHandle where F: FnOnce() -> T + Send + 'static, T: Send + 'static, { self.$member.spawn_blocking(f) } // `track_caller` required for tokio-console #[inline] #[track_caller] fn reenter_block_on(&self, future: F) -> F::Output where F: futures::Future, F::Output: Send + 'static { self.$member.reenter_block_on(future) } } impl $crate::traits::ToplevelBlockOn for $t { // `track_caller` required for tokio-console #[inline] #[track_caller] fn block_on(&self, future: F) -> F::Output { self.$member.block_on(future) } } impl $crate::traits::SleepProvider for $t { type SleepFuture = <$mty as $crate::traits::SleepProvider>::SleepFuture; #[inline] fn sleep(&self, duration: std::time::Duration) -> Self::SleepFuture { self.$member.sleep(duration) } } impl $crate::CoarseTimeProvider for $t { #[inline] fn now_coarse(&self) -> $crate::CoarseInstant { self.$member.now_coarse() } } #[async_trait::async_trait] impl $crate::traits::NetStreamProvider for $t { type Stream = <$mty as $crate::traits::NetStreamProvider>::Stream; type Listener = <$mty as $crate::traits::NetStreamProvider>::Listener; #[inline] #[tracing::instrument(skip_all, level = "trace")] async fn connect(&self, addr: &std::net::SocketAddr) -> std::io::Result { self.$member.connect(addr).await } #[inline] async fn listen(&self, addr: &std::net::SocketAddr) -> std::io::Result { self.$member.listen(addr).await } } #[async_trait::async_trait] impl $crate::traits::NetStreamProvider for $t { type Stream = <$mty as $crate::traits::NetStreamProvider>::Stream; type Listener = <$mty as $crate::traits::NetStreamProvider>::Listener; #[inline] #[tracing::instrument(skip_all, level = "trace")] async fn connect(&self, addr: &tor_general_addr::unix::SocketAddr) -> std::io::Result { self.$member.connect(addr).await } #[inline] async fn listen(&self, addr: &tor_general_addr::unix::SocketAddr) -> std::io::Result { self.$member.listen(addr).await } } impl $crate::traits::TlsProvider for $t where S: futures::AsyncRead + futures::AsyncWrite + $crate::traits::StreamOps + Unpin + Send + 'static, { type Connector = <$mty as $crate::traits::TlsProvider>::Connector; type TlsStream = <$mty as $crate::traits::TlsProvider>::TlsStream; #[inline] fn tls_connector(&self) -> Self::Connector { self.$member.tls_connector() } #[inline] fn supports_keying_material_export(&self) -> bool { <$mty as $crate::traits::TlsProvider>::supports_keying_material_export(&self.$member) } } #[async_trait::async_trait] impl $crate::traits::UdpProvider for $t { type UdpSocket = <$mty as $crate::traits::UdpProvider>::UdpSocket; #[inline] async fn bind(&self, addr: &std::net::SocketAddr) -> std::io::Result { self.$member.bind(addr).await } } impl std::fmt::Debug for $t { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct(stringify!($t)).finish_non_exhaustive() } } // This boilerplate will fail unless $t implements Runtime. #[allow(unused)] const _ : () = { fn assert_runtime() {} fn check() { assert_runtime::<$t>(); } }; } } #[allow(unused)] // Can be unused if no runtimes are declared. pub(crate) use implement_opaque_runtime;