From 4f8bc4f42508fb8a9cdead50b2a99ae6181154e7 Mon Sep 17 00:00:00 2001 From: Nathaniel Ford Date: Thu, 4 Jun 2026 21:09:24 +0000 Subject: [PATCH 1/3] Introduce IntoDynChannelCredentials trait for flexible channel credentials. To support creating channels with various credentials configurations, we need to accept different credential representations (such as concrete types or Arc-wrapped trait objects). This trait provides a common conversion interface to type-erase these representations internally. This refactoring is isolated to its own commit to keep subsequent feature commits focused and legible. --- grpc/src/credentials/client.rs | 22 ++++++++++++++++++++++ grpc/src/credentials/dyn_wrapper.rs | 12 +++++++++++- grpc/src/credentials/local.rs | 12 ++++++++++++ grpc/src/credentials/mod.rs | 4 ++++ grpc/src/credentials/rustls/client/mod.rs | 12 ++++++++++++ 5 files changed, 61 insertions(+), 1 deletion(-) diff --git a/grpc/src/credentials/client.rs b/grpc/src/credentials/client.rs index 273d4ca7c..d1ab739f6 100644 --- a/grpc/src/credentials/client.rs +++ b/grpc/src/credentials/client.rs @@ -196,6 +196,28 @@ impl ChannelCredentials for CompositeChannelCredentials crate::credentials::dyn_wrapper::IntoDynChannelCredentials + for CompositeChannelCredentials +where + T: ChannelCredentials + 'static, + T::Output: crate::rt::GrpcEndpoint, +{ + fn into_dyn_creds(self) -> Arc { + Arc::new(self) as Arc + } +} + +impl crate::credentials::dyn_wrapper::IntoDynChannelCredentials + for Arc> +where + T: ChannelCredentials + 'static, + T::Output: crate::rt::GrpcEndpoint, +{ + fn into_dyn_creds(self) -> Arc { + self as Arc + } +} + #[cfg(test)] mod tests { use tokio::net::TcpListener; diff --git a/grpc/src/credentials/dyn_wrapper.rs b/grpc/src/credentials/dyn_wrapper.rs index 09543d1c5..1b6056d68 100644 --- a/grpc/src/credentials/dyn_wrapper.rs +++ b/grpc/src/credentials/dyn_wrapper.rs @@ -44,7 +44,7 @@ type BoxEndpoint = Box; // Bridge trait for type erasure. #[async_trait] -pub(crate) trait DynChannelCredentials: Send + Sync { +pub trait DynChannelCredentials: Send + Sync { async fn dyn_connect( &self, authority: &Authority, @@ -121,6 +121,16 @@ impl ChannelCredentials for Arc { } } +pub trait IntoDynChannelCredentials { + fn into_dyn_creds(self) -> Arc; +} + +impl IntoDynChannelCredentials for Arc { + fn into_dyn_creds(self) -> Arc { + self + } +} + // Bridge trait for type erasure. #[async_trait] pub(crate) trait DynServerCredentials: Send + Sync { diff --git a/grpc/src/credentials/local.rs b/grpc/src/credentials/local.rs index ff0fd314b..3d5e41f26 100644 --- a/grpc/src/credentials/local.rs +++ b/grpc/src/credentials/local.rs @@ -147,6 +147,18 @@ impl ChannelCredentials for LocalChannelCredentials { } } +impl crate::credentials::dyn_wrapper::IntoDynChannelCredentials for LocalChannelCredentials { + fn into_dyn_creds(self) -> Arc { + Arc::new(self) as Arc + } +} + +impl crate::credentials::dyn_wrapper::IntoDynChannelCredentials for Arc { + fn into_dyn_creds(self) -> Arc { + self as Arc + } +} + /// An implementation of [`ServerCredentials`] for local connections to pair /// with a client using [`LocalChannelCredentials`]. #[derive(Debug, Clone, Default)] diff --git a/grpc/src/credentials/mod.rs b/grpc/src/credentials/mod.rs index 68a56600f..112318b53 100644 --- a/grpc/src/credentials/mod.rs +++ b/grpc/src/credentials/mod.rs @@ -38,6 +38,10 @@ pub mod call; pub(crate) mod client; pub(crate) mod dyn_wrapper; +#[doc(hidden)] +pub use dyn_wrapper::DynChannelCredentials; +#[doc(hidden)] +pub use dyn_wrapper::IntoDynChannelCredentials; mod local; #[cfg(feature = "tls-rustls")] pub mod rustls; diff --git a/grpc/src/credentials/rustls/client/mod.rs b/grpc/src/credentials/rustls/client/mod.rs index 4c3f46154..b3ea36fc2 100644 --- a/grpc/src/credentials/rustls/client/mod.rs +++ b/grpc/src/credentials/rustls/client/mod.rs @@ -280,3 +280,15 @@ impl ChannelCredentials for RustlsChannelCredendials { None } } + +impl crate::credentials::dyn_wrapper::IntoDynChannelCredentials for RustlsChannelCredendials { + fn into_dyn_creds(self) -> Arc { + Arc::new(self) as Arc + } +} + +impl crate::credentials::dyn_wrapper::IntoDynChannelCredentials for Arc { + fn into_dyn_creds(self) -> Arc { + self as Arc + } +} From 74df345a0c1873bc2939fd348c9bbcea970563f6 Mon Sep 17 00:00:00 2001 From: Nathaniel Ford Date: Thu, 11 Jun 2026 18:13:03 +0000 Subject: [PATCH 2/3] Implement ChannelCredentials directly for dyn DynChannelCredentials and Arc to eliminate custom conversion boilerplate. --- grpc/src/credentials/client.rs | 21 ------------- grpc/src/credentials/dyn_wrapper.rs | 36 ++++++++++++++++------- grpc/src/credentials/local.rs | 11 ------- grpc/src/credentials/mod.rs | 2 -- grpc/src/credentials/rustls/client/mod.rs | 11 ------- 5 files changed, 25 insertions(+), 56 deletions(-) diff --git a/grpc/src/credentials/client.rs b/grpc/src/credentials/client.rs index d1ab739f6..ccdb48b08 100644 --- a/grpc/src/credentials/client.rs +++ b/grpc/src/credentials/client.rs @@ -196,27 +196,6 @@ impl ChannelCredentials for CompositeChannelCredentials crate::credentials::dyn_wrapper::IntoDynChannelCredentials - for CompositeChannelCredentials -where - T: ChannelCredentials + 'static, - T::Output: crate::rt::GrpcEndpoint, -{ - fn into_dyn_creds(self) -> Arc { - Arc::new(self) as Arc - } -} - -impl crate::credentials::dyn_wrapper::IntoDynChannelCredentials - for Arc> -where - T: ChannelCredentials + 'static, - T::Output: crate::rt::GrpcEndpoint, -{ - fn into_dyn_creds(self) -> Arc { - self as Arc - } -} #[cfg(test)] mod tests { diff --git a/grpc/src/credentials/dyn_wrapper.rs b/grpc/src/credentials/dyn_wrapper.rs index 1b6056d68..652f08025 100644 --- a/grpc/src/credentials/dyn_wrapper.rs +++ b/grpc/src/credentials/dyn_wrapper.rs @@ -95,7 +95,7 @@ where } } -impl ChannelCredentials for Arc { +impl ChannelCredentials for dyn DynChannelCredentials { type ContextType = Box; type Output = BoxEndpoint; @@ -107,30 +107,44 @@ impl ChannelCredentials for Arc { runtime: &GrpcRuntime, _token: private::Internal, ) -> Result, Self::ContextType>, String> { - (**self) - .dyn_connect(authority, Box::new(source), info, runtime) + self.dyn_connect(authority, Box::new(source), info, runtime) .await } fn get_call_credentials(&self, _: private::Internal) -> Option<&Arc> { - (**self).get_call_credentials() + self.get_call_credentials() } fn info(&self) -> &ProtocolInfo { - (**self).info() + self.info() } } -pub trait IntoDynChannelCredentials { - fn into_dyn_creds(self) -> Arc; -} +impl ChannelCredentials for Arc { + type ContextType = T::ContextType; + type Output = T::Output; -impl IntoDynChannelCredentials for Arc { - fn into_dyn_creds(self) -> Arc { - self + async fn connect( + &self, + authority: &Authority, + source: Input, + info: &ClientHandshakeInfo, + runtime: &GrpcRuntime, + token: private::Internal, + ) -> Result, Self::ContextType>, String> { + (**self).connect(authority, source, info, runtime, token).await + } + + fn get_call_credentials(&self, token: private::Internal) -> Option<&Arc> { + (**self).get_call_credentials(token) + } + + fn info(&self) -> &ProtocolInfo { + (**self).info() } } + // Bridge trait for type erasure. #[async_trait] pub(crate) trait DynServerCredentials: Send + Sync { diff --git a/grpc/src/credentials/local.rs b/grpc/src/credentials/local.rs index 3d5e41f26..4b9c73fe8 100644 --- a/grpc/src/credentials/local.rs +++ b/grpc/src/credentials/local.rs @@ -147,17 +147,6 @@ impl ChannelCredentials for LocalChannelCredentials { } } -impl crate::credentials::dyn_wrapper::IntoDynChannelCredentials for LocalChannelCredentials { - fn into_dyn_creds(self) -> Arc { - Arc::new(self) as Arc - } -} - -impl crate::credentials::dyn_wrapper::IntoDynChannelCredentials for Arc { - fn into_dyn_creds(self) -> Arc { - self as Arc - } -} /// An implementation of [`ServerCredentials`] for local connections to pair /// with a client using [`LocalChannelCredentials`]. diff --git a/grpc/src/credentials/mod.rs b/grpc/src/credentials/mod.rs index 112318b53..e71b8ce7e 100644 --- a/grpc/src/credentials/mod.rs +++ b/grpc/src/credentials/mod.rs @@ -40,8 +40,6 @@ pub(crate) mod client; pub(crate) mod dyn_wrapper; #[doc(hidden)] pub use dyn_wrapper::DynChannelCredentials; -#[doc(hidden)] -pub use dyn_wrapper::IntoDynChannelCredentials; mod local; #[cfg(feature = "tls-rustls")] pub mod rustls; diff --git a/grpc/src/credentials/rustls/client/mod.rs b/grpc/src/credentials/rustls/client/mod.rs index b3ea36fc2..a67d571cc 100644 --- a/grpc/src/credentials/rustls/client/mod.rs +++ b/grpc/src/credentials/rustls/client/mod.rs @@ -281,14 +281,3 @@ impl ChannelCredentials for RustlsChannelCredendials { } } -impl crate::credentials::dyn_wrapper::IntoDynChannelCredentials for RustlsChannelCredendials { - fn into_dyn_creds(self) -> Arc { - Arc::new(self) as Arc - } -} - -impl crate::credentials::dyn_wrapper::IntoDynChannelCredentials for Arc { - fn into_dyn_creds(self) -> Arc { - self as Arc - } -} From ee091b361e0e7038f4e53d283ff863ba34eb90e1 Mon Sep 17 00:00:00 2001 From: Nathaniel Ford Date: Thu, 11 Jun 2026 18:41:15 +0000 Subject: [PATCH 3/3] Cleanup. --- grpc/src/credentials/client.rs | 1 - grpc/src/credentials/dyn_wrapper.rs | 7 ++++--- grpc/src/credentials/local.rs | 1 - grpc/src/credentials/mod.rs | 2 -- grpc/src/credentials/rustls/client/mod.rs | 1 - 5 files changed, 4 insertions(+), 8 deletions(-) diff --git a/grpc/src/credentials/client.rs b/grpc/src/credentials/client.rs index ccdb48b08..273d4ca7c 100644 --- a/grpc/src/credentials/client.rs +++ b/grpc/src/credentials/client.rs @@ -196,7 +196,6 @@ impl ChannelCredentials for CompositeChannelCredentials; // Bridge trait for type erasure. #[async_trait] -pub trait DynChannelCredentials: Send + Sync { +pub(crate) trait DynChannelCredentials: Send + Sync { async fn dyn_connect( &self, authority: &Authority, @@ -132,7 +132,9 @@ impl ChannelCredentials for Arc { runtime: &GrpcRuntime, token: private::Internal, ) -> Result, Self::ContextType>, String> { - (**self).connect(authority, source, info, runtime, token).await + (**self) + .connect(authority, source, info, runtime, token) + .await } fn get_call_credentials(&self, token: private::Internal) -> Option<&Arc> { @@ -144,7 +146,6 @@ impl ChannelCredentials for Arc { } } - // Bridge trait for type erasure. #[async_trait] pub(crate) trait DynServerCredentials: Send + Sync { diff --git a/grpc/src/credentials/local.rs b/grpc/src/credentials/local.rs index 4b9c73fe8..ff0fd314b 100644 --- a/grpc/src/credentials/local.rs +++ b/grpc/src/credentials/local.rs @@ -147,7 +147,6 @@ impl ChannelCredentials for LocalChannelCredentials { } } - /// An implementation of [`ServerCredentials`] for local connections to pair /// with a client using [`LocalChannelCredentials`]. #[derive(Debug, Clone, Default)] diff --git a/grpc/src/credentials/mod.rs b/grpc/src/credentials/mod.rs index e71b8ce7e..68a56600f 100644 --- a/grpc/src/credentials/mod.rs +++ b/grpc/src/credentials/mod.rs @@ -38,8 +38,6 @@ pub mod call; pub(crate) mod client; pub(crate) mod dyn_wrapper; -#[doc(hidden)] -pub use dyn_wrapper::DynChannelCredentials; mod local; #[cfg(feature = "tls-rustls")] pub mod rustls; diff --git a/grpc/src/credentials/rustls/client/mod.rs b/grpc/src/credentials/rustls/client/mod.rs index a67d571cc..4c3f46154 100644 --- a/grpc/src/credentials/rustls/client/mod.rs +++ b/grpc/src/credentials/rustls/client/mod.rs @@ -280,4 +280,3 @@ impl ChannelCredentials for RustlsChannelCredendials { None } } -