1use std::fmt;
2use std::io::IoSlice;
3use std::pin::Pin;
4use std::task::{Context as TaskContext, Poll};
5use tokio::io::{AsyncRead, AsyncWrite, Error as IoError, ReadBuf, Result as IoResult};
6
7#[macro_export]
8#[doc(hidden)]
9macro_rules! __impl_either {
12 ($macro:ident) => {
13 $macro!(Either, A, B,);
14 $macro!(Either3, A, B, C,);
15 $macro!(Either4, A, B, C, D,);
16 $macro!(Either5, A, B, C, D, E,);
17 $macro!(Either6, A, B, C, D, E, F,);
18 $macro!(Either7, A, B, C, D, E, F, G,);
19 $macro!(Either8, A, B, C, D, E, F, G, H,);
20 $macro!(Either9, A, B, C, D, E, F, G, H, I,);
21 };
22}
23
24#[doc(inline)]
25pub use crate::__impl_either as impl_either;
26
27macro_rules! define_either {
28 ($id:ident, $($param:ident),+ $(,)?) => {
29 pub enum $id<$($param),+> {
38 $(
39 $param($param),
41 )+
42 }
43
44 impl<$($param),+> Clone for $id<$($param),+>
45 where
46 $($param: Clone),+
47 {
48 fn clone(&self) -> Self {
49 match self {
50 $(
51 $id::$param(s) => $id::$param(s.clone()),
52 )+
53 }
54 }
55 }
56
57 impl<$($param),+> fmt::Debug for $id<$($param),+>
58 where
59 $($param: fmt::Debug),+
60 {
61 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
62 match self {
63 $(
64 $id::$param(s) => write!(f, "{:?}", s),
65 )+
66 }
67 }
68 }
69
70 impl<$($param),+> fmt::Display for $id<$($param),+>
71 where
72 $($param: fmt::Display),+
73 {
74 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
75 match self {
76 $(
77 $id::$param(s) => write!(f, "{}", s),
78 )+
79 }
80 }
81 }
82
83
84 impl<$($param),+> $id<$($param),+> {
85 fn as_pin_mut(self: Pin<&mut Self>) -> $id<$(Pin<&mut $param>),+> {
88 unsafe {
94 match self.get_unchecked_mut() {
95 $(
96 Self::$param(inner) => $id::$param(Pin::new_unchecked(inner)),
97 )+
98 }
99 }
100 }
101 }
102
103 impl<$($param),+, Output> std::future::Future for $id<$($param),+>
104 where
105 $($param: std::future::Future<Output = Output>),+
106 {
107 type Output = Output;
108
109 fn poll(self: Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> Poll<Self::Output> {
110 match self.as_pin_mut() {
111 $(
112 $id::$param(fut) => fut.poll(cx),
113 )+
114 }
115 }
116 }
117 };
118}
119
120impl_either!(define_either);
121
122macro_rules! impl_iterator_either {
123 ($id:ident, $($param:ident),+ $(,)?) => {
124 impl<$($param),+, Item> Iterator for $id<$($param),+>
125 where
126 $($param: Iterator<Item = Item>),+,
127 {
128 type Item = Item;
129
130 fn next(&mut self) -> Option<Item> {
131 match self {
132 $(
133 $id::$param(iter) => iter.next(),
134 )+
135 }
136 }
137
138 fn size_hint(&self) -> (usize, Option<usize>) {
139 match self {
140 $(
141 $id::$param(iter) => iter.size_hint(),
142 )+
143 }
144 }
145 }
146 };
147}
148
149impl_either!(impl_iterator_either);
150
151macro_rules! impl_async_read_write_either {
152 ($id:ident, $($param:ident),+ $(,)?) => {
153 impl<$($param),+> AsyncRead for $id<$($param),+>
154 where
155 $($param: AsyncRead),+,
156 {
157 fn poll_read(
158 self: Pin<&mut Self>,
159 cx: &mut TaskContext<'_>,
160 buf: &mut ReadBuf<'_>,
161 ) -> Poll<IoResult<()>> {
162 match self.as_pin_mut() {
163 $(
164 $id::$param(reader) => reader.poll_read(cx, buf),
165 )+
166 }
167 }
168 }
169
170 impl<$($param),+> AsyncWrite for $id<$($param),+>
171 where
172 $($param: AsyncWrite),+,
173 {
174 fn poll_write(
175 self: Pin<&mut Self>,
176 cx: &mut TaskContext<'_>,
177 buf: &[u8],
178 ) -> Poll<Result<usize, IoError>> {
179 match self.as_pin_mut() {
180 $(
181 $id::$param(writer) => writer.poll_write(cx, buf),
182 )+
183 }
184 }
185
186 fn poll_flush(self: Pin<&mut Self>, cx: &mut TaskContext<'_>) -> Poll<Result<(), IoError>> {
187 match self.as_pin_mut() {
188 $(
189 $id::$param(writer) => writer.poll_flush(cx),
190 )+
191 }
192 }
193
194 fn poll_shutdown(self: Pin<&mut Self>, cx: &mut TaskContext<'_>) -> Poll<Result<(), IoError>> {
195 match self.as_pin_mut() {
196 $(
197 $id::$param(writer) => writer.poll_shutdown(cx),
198 )+
199 }
200 }
201
202 fn poll_write_vectored(
203 self: Pin<&mut Self>,
204 cx: &mut TaskContext<'_>,
205 bufs: &[IoSlice<'_>],
206 ) -> Poll<Result<usize, IoError>> {
207 match self.as_pin_mut() {
208 $(
209 $id::$param(writer) => writer.poll_write_vectored(cx, bufs),
210 )+
211 }
212 }
213
214 fn is_write_vectored(&self) -> bool {
215 match self {
216 $(
217 $id::$param(writer) => writer.is_write_vectored(),
218 )+
219 }
220 }
221 }
222 };
223}
224
225impl_either!(impl_async_read_write_either);