1use crate::{Transport, TransportError, TransportFut};
2use alloy_json_rpc::{RequestPacket, ResponsePacket};
3use std::{any::TypeId, fmt};
4use tower::Service;
5
6#[expect(unnameable_types)]
7mod private {
8 pub trait Sealed {}
9 impl<T: super::Transport + Clone> Sealed for T {}
10}
11
12pub trait IntoBoxTransport: Transport + Clone + private::Sealed {
17 fn into_box_transport(self) -> BoxTransport;
19}
20
21impl<T: Transport + Clone> IntoBoxTransport for T {
22 fn into_box_transport(self) -> BoxTransport {
23 if TypeId::of::<T>() == TypeId::of::<BoxTransport>() {
25 let this = std::mem::ManuallyDrop::new(self);
29 return unsafe { std::mem::transmute_copy(&this) };
30 }
31 BoxTransport { inner: Box::new(self) }
32 }
33}
34
35pub struct BoxTransport {
45 inner: Box<dyn CloneTransport>,
46}
47
48impl BoxTransport {
49 #[inline]
51 pub fn new<T: IntoBoxTransport>(transport: T) -> Self {
52 transport.into_box_transport()
53 }
54
55 #[inline]
57 pub fn as_any(&self) -> &dyn std::any::Any {
58 &*self.inner
59 }
60}
61
62impl fmt::Debug for BoxTransport {
63 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
64 f.debug_struct("BoxTransport").finish_non_exhaustive()
65 }
66}
67
68impl Clone for BoxTransport {
69 fn clone(&self) -> Self {
70 Self { inner: self.inner.clone_box() }
71 }
72}
73
74trait CloneTransport: Transport + std::any::Any {
76 fn clone_box(&self) -> Box<dyn CloneTransport + Send + Sync>;
77}
78
79impl<T> CloneTransport for T
80where
81 T: Transport + Clone + Send + Sync,
82{
83 #[inline]
84 fn clone_box(&self) -> Box<dyn CloneTransport + Send + Sync> {
85 Box::new(self.clone())
86 }
87}
88
89impl Service<RequestPacket> for BoxTransport {
90 type Response = ResponsePacket;
91 type Error = TransportError;
92 type Future = TransportFut<'static>;
93
94 #[inline]
95 fn poll_ready(
96 &mut self,
97 cx: &mut std::task::Context<'_>,
98 ) -> std::task::Poll<Result<(), Self::Error>> {
99 self.inner.poll_ready(cx)
100 }
101
102 #[inline]
103 fn call(&mut self, req: RequestPacket) -> Self::Future {
104 self.inner.call(req)
105 }
106}
107
108#[cfg(test)]
109mod test {
110 use super::*;
111
112 #[derive(Clone)]
113 struct DummyTransport<T>(T);
114 impl<T> Service<RequestPacket> for DummyTransport<T> {
115 type Response = ResponsePacket;
116 type Error = TransportError;
117 type Future = TransportFut<'static>;
118
119 fn poll_ready(
120 &mut self,
121 _cx: &mut std::task::Context<'_>,
122 ) -> std::task::Poll<Result<(), Self::Error>> {
123 unimplemented!()
124 }
125
126 fn call(&mut self, _req: RequestPacket) -> Self::Future {
127 unimplemented!()
128 }
129 }
130
131 const fn _compile_check() {
133 const fn inner<T>()
134 where
135 T: Transport + CloneTransport + Send + Sync + Clone + IntoBoxTransport + 'static,
136 {
137 }
138 inner::<BoxTransport>();
139 }
140
141 #[test]
142 fn no_reboxing() {
143 let id = TypeId::of::<DummyTransport<()>>();
144 no_reboxing_(DummyTransport(()), id);
145 no_reboxing_(BoxTransport::new(DummyTransport(())), id);
146
147 let wrap = String::from("hello");
148 let id = TypeId::of::<DummyTransport<String>>();
149 no_reboxing_(DummyTransport(wrap.clone()), id);
150 no_reboxing_(BoxTransport::new(DummyTransport(wrap)), id);
151 }
152
153 fn no_reboxing_<T: IntoBoxTransport>(t: T, id: TypeId) {
154 eprintln!("{}", std::any::type_name::<T>());
155
156 let t1 = BoxTransport::new(t);
157 let t1p = std::ptr::addr_of!(*t1.inner);
158 let t1id = t1.as_any().type_id();
159
160 let t2 = BoxTransport::new(t1);
162 let t2p = std::ptr::addr_of!(*t2.inner);
163 let t2id = t2.as_any().type_id();
164
165 assert_eq!(t1id, id);
166 assert_eq!(t1id, t2id);
167 assert!(std::ptr::eq(t1p, t2p));
168 }
169}