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.as_any()
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 fn as_any(&self) -> &dyn std::any::Any;
78}
79
80impl<T> CloneTransport for T
81where
82 T: Transport + Clone + Send + Sync,
83{
84 #[inline]
85 fn clone_box(&self) -> Box<dyn CloneTransport + Send + Sync> {
86 Box::new(self.clone())
87 }
88
89 #[inline]
90 fn as_any(&self) -> &dyn std::any::Any {
91 self
92 }
93}
94
95impl Service<RequestPacket> for BoxTransport {
96 type Response = ResponsePacket;
97 type Error = TransportError;
98 type Future = TransportFut<'static>;
99
100 #[inline]
101 fn poll_ready(
102 &mut self,
103 cx: &mut std::task::Context<'_>,
104 ) -> std::task::Poll<Result<(), Self::Error>> {
105 self.inner.poll_ready(cx)
106 }
107
108 #[inline]
109 fn call(&mut self, req: RequestPacket) -> Self::Future {
110 self.inner.call(req)
111 }
112}
113
114#[cfg(test)]
115mod test {
116 use super::*;
117
118 #[derive(Clone)]
119 struct DummyTransport<T>(T);
120 impl<T> Service<RequestPacket> for DummyTransport<T> {
121 type Response = ResponsePacket;
122 type Error = TransportError;
123 type Future = TransportFut<'static>;
124
125 fn poll_ready(
126 &mut self,
127 _cx: &mut std::task::Context<'_>,
128 ) -> std::task::Poll<Result<(), Self::Error>> {
129 unimplemented!()
130 }
131
132 fn call(&mut self, _req: RequestPacket) -> Self::Future {
133 unimplemented!()
134 }
135 }
136
137 const fn _compile_check() {
139 const fn inner<T>()
140 where
141 T: Transport + CloneTransport + Send + Sync + Clone + IntoBoxTransport + 'static,
142 {
143 }
144 inner::<BoxTransport>();
145 }
146
147 #[test]
148 fn no_reboxing() {
149 let id = TypeId::of::<DummyTransport<()>>();
150 no_reboxing_(DummyTransport(()), id);
151 no_reboxing_(BoxTransport::new(DummyTransport(())), id);
152
153 let wrap = String::from("hello");
154 let id = TypeId::of::<DummyTransport<String>>();
155 no_reboxing_(DummyTransport(wrap.clone()), id);
156 no_reboxing_(BoxTransport::new(DummyTransport(wrap)), id);
157 }
158
159 fn no_reboxing_<T: IntoBoxTransport>(t: T, id: TypeId) {
160 eprintln!("{}", std::any::type_name::<T>());
161
162 let t1 = BoxTransport::new(t);
163 let t1p = std::ptr::addr_of!(*t1.inner);
164 let t1id = t1.as_any().type_id();
165
166 let t2 = BoxTransport::new(t1);
168 let t2p = std::ptr::addr_of!(*t2.inner);
169 let t2id = t2.as_any().type_id();
170
171 assert_eq!(t1id, id);
172 assert_eq!(t1id, t2id);
173 assert!(std::ptr::eq(t1p, t2p));
174 }
175}