Skip to content

Commit c88ad9b

Browse files
thomaseizingertaiki-e
authored andcommitted
Add Either::as_pin_mut and Either::as_pin_ref (#2691)
1 parent bf3504b commit c88ad9b

File tree

1 file changed

+39
-19
lines changed

1 file changed

+39
-19
lines changed

futures-util/src/future/either.rs

+39-19
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,31 @@ pub enum Either<A, B> {
3333
}
3434

3535
impl<A, B> Either<A, B> {
36-
fn project(self: Pin<&mut Self>) -> Either<Pin<&mut A>, Pin<&mut B>> {
36+
/// Convert `Pin<&Either<A, B>>` to `Either<Pin<&A>, Pin<&B>>`,
37+
/// pinned projections of the inner variants.
38+
pub fn as_pin_ref(self: Pin<&Self>) -> Either<Pin<&A>, Pin<&B>> {
39+
// SAFETY: We can use `new_unchecked` because the `inner` parts are
40+
// guaranteed to be pinned, as they come from `self` which is pinned.
3741
unsafe {
38-
match self.get_unchecked_mut() {
39-
Either::Left(a) => Either::Left(Pin::new_unchecked(a)),
40-
Either::Right(b) => Either::Right(Pin::new_unchecked(b)),
42+
match *Pin::get_ref(self) {
43+
Either::Left(ref inner) => Either::Left(Pin::new_unchecked(inner)),
44+
Either::Right(ref inner) => Either::Right(Pin::new_unchecked(inner)),
45+
}
46+
}
47+
}
48+
49+
/// Convert `Pin<&mut Either<A, B>>` to `Either<Pin<&mut A>, Pin<&mut B>>`,
50+
/// pinned projections of the inner variants.
51+
pub fn as_pin_mut(self: Pin<&mut Self>) -> Either<Pin<&mut A>, Pin<&mut B>> {
52+
// SAFETY: `get_unchecked_mut` is fine because we don't move anything.
53+
// We can use `new_unchecked` because the `inner` parts are guaranteed
54+
// to be pinned, as they come from `self` which is pinned, and we never
55+
// offer an unpinned `&mut A` or `&mut B` through `Pin<&mut Self>`. We
56+
// also don't have an implementation of `Drop`, nor manual `Unpin`.
57+
unsafe {
58+
match *Pin::get_unchecked_mut(self) {
59+
Either::Left(ref mut inner) => Either::Left(Pin::new_unchecked(inner)),
60+
Either::Right(ref mut inner) => Either::Right(Pin::new_unchecked(inner)),
4161
}
4262
}
4363
}
@@ -85,7 +105,7 @@ where
85105
type Output = A::Output;
86106

87107
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
88-
match self.project() {
108+
match self.as_pin_mut() {
89109
Either::Left(x) => x.poll(cx),
90110
Either::Right(x) => x.poll(cx),
91111
}
@@ -113,7 +133,7 @@ where
113133
type Item = A::Item;
114134

115135
fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
116-
match self.project() {
136+
match self.as_pin_mut() {
117137
Either::Left(x) => x.poll_next(cx),
118138
Either::Right(x) => x.poll_next(cx),
119139
}
@@ -149,28 +169,28 @@ where
149169
type Error = A::Error;
150170

151171
fn poll_ready(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
152-
match self.project() {
172+
match self.as_pin_mut() {
153173
Either::Left(x) => x.poll_ready(cx),
154174
Either::Right(x) => x.poll_ready(cx),
155175
}
156176
}
157177

158178
fn start_send(self: Pin<&mut Self>, item: Item) -> Result<(), Self::Error> {
159-
match self.project() {
179+
match self.as_pin_mut() {
160180
Either::Left(x) => x.start_send(item),
161181
Either::Right(x) => x.start_send(item),
162182
}
163183
}
164184

165185
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
166-
match self.project() {
186+
match self.as_pin_mut() {
167187
Either::Left(x) => x.poll_flush(cx),
168188
Either::Right(x) => x.poll_flush(cx),
169189
}
170190
}
171191

172192
fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
173-
match self.project() {
193+
match self.as_pin_mut() {
174194
Either::Left(x) => x.poll_close(cx),
175195
Either::Right(x) => x.poll_close(cx),
176196
}
@@ -198,7 +218,7 @@ mod if_std {
198218
cx: &mut Context<'_>,
199219
buf: &mut [u8],
200220
) -> Poll<Result<usize>> {
201-
match self.project() {
221+
match self.as_pin_mut() {
202222
Either::Left(x) => x.poll_read(cx, buf),
203223
Either::Right(x) => x.poll_read(cx, buf),
204224
}
@@ -209,7 +229,7 @@ mod if_std {
209229
cx: &mut Context<'_>,
210230
bufs: &mut [IoSliceMut<'_>],
211231
) -> Poll<Result<usize>> {
212-
match self.project() {
232+
match self.as_pin_mut() {
213233
Either::Left(x) => x.poll_read_vectored(cx, bufs),
214234
Either::Right(x) => x.poll_read_vectored(cx, bufs),
215235
}
@@ -226,7 +246,7 @@ mod if_std {
226246
cx: &mut Context<'_>,
227247
buf: &[u8],
228248
) -> Poll<Result<usize>> {
229-
match self.project() {
249+
match self.as_pin_mut() {
230250
Either::Left(x) => x.poll_write(cx, buf),
231251
Either::Right(x) => x.poll_write(cx, buf),
232252
}
@@ -237,21 +257,21 @@ mod if_std {
237257
cx: &mut Context<'_>,
238258
bufs: &[IoSlice<'_>],
239259
) -> Poll<Result<usize>> {
240-
match self.project() {
260+
match self.as_pin_mut() {
241261
Either::Left(x) => x.poll_write_vectored(cx, bufs),
242262
Either::Right(x) => x.poll_write_vectored(cx, bufs),
243263
}
244264
}
245265

246266
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>> {
247-
match self.project() {
267+
match self.as_pin_mut() {
248268
Either::Left(x) => x.poll_flush(cx),
249269
Either::Right(x) => x.poll_flush(cx),
250270
}
251271
}
252272

253273
fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>> {
254-
match self.project() {
274+
match self.as_pin_mut() {
255275
Either::Left(x) => x.poll_close(cx),
256276
Either::Right(x) => x.poll_close(cx),
257277
}
@@ -268,7 +288,7 @@ mod if_std {
268288
cx: &mut Context<'_>,
269289
pos: SeekFrom,
270290
) -> Poll<Result<u64>> {
271-
match self.project() {
291+
match self.as_pin_mut() {
272292
Either::Left(x) => x.poll_seek(cx, pos),
273293
Either::Right(x) => x.poll_seek(cx, pos),
274294
}
@@ -281,14 +301,14 @@ mod if_std {
281301
B: AsyncBufRead,
282302
{
283303
fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<&[u8]>> {
284-
match self.project() {
304+
match self.as_pin_mut() {
285305
Either::Left(x) => x.poll_fill_buf(cx),
286306
Either::Right(x) => x.poll_fill_buf(cx),
287307
}
288308
}
289309

290310
fn consume(self: Pin<&mut Self>, amt: usize) {
291-
match self.project() {
311+
match self.as_pin_mut() {
292312
Either::Left(x) => x.consume(amt),
293313
Either::Right(x) => x.consume(amt),
294314
}

0 commit comments

Comments
 (0)