Skip to content

Commit 0e11249

Browse files
authored
Merge pull request #77 from cuviper/pin-future
Add `Pin` projections and implement `Future` (MSRV 1.36)
2 parents fad7d3a + a966956 commit 0e11249

File tree

4 files changed

+62
-10
lines changed

4 files changed

+62
-10
lines changed

.github/workflows/ci.yml

+1-7
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ jobs:
1313
fail-fast: false
1414
matrix:
1515
rust:
16-
- 1.31.0 # MSRV
16+
- 1.36.0 # MSRV
1717
- stable
1818
- beta
1919
- nightly
@@ -30,12 +30,6 @@ jobs:
3030
with:
3131
toolchain: ${{ matrix.rust }}
3232

33-
- name: (1.31.0) Downgrade serde_json
34-
if: ${{ matrix.rust == '1.31.0' }}
35-
run: |
36-
cargo generate-lockfile
37-
cargo update -p serde_json --precise 1.0.39
38-
3933
- name: Build (no_std)
4034
run: cargo build --no-default-features
4135

Cargo.toml

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
[package]
22
name = "either"
3-
version = "1.7.0"
3+
version = "1.8.0"
44
authors = ["bluss"]
55
edition = "2018"
6-
rust-version = "1.31"
6+
rust-version = "1.36"
77

88
license = "MIT/Apache-2.0"
99
repository = "https://github.com/bluss/either"

README.rst

+12-1
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,23 @@ __ https://docs.rs/either/
2525
How to use with cargo::
2626

2727
[dependencies]
28-
either = "1.7"
28+
either = "1.8"
2929

3030

3131
Recent Changes
3232
--------------
3333

34+
- 1.8.0
35+
36+
- **MSRV**: ``either`` now requires Rust 1.36 or later.
37+
38+
- Add new methods ``.as_pin_ref()`` and ``.as_pin_mut()`` to project a
39+
pinned ``Either`` as inner ``Pin`` variants, by @cuviper (#77)
40+
41+
- Implement the ``Future`` trait, by @cuviper (#77)
42+
43+
- Specialize more methods of the ``io`` traits, by @Kixunil and @cuviper (#75)
44+
3445
- 1.7.0
3546

3647
- **MSRV**: ``either`` now requires Rust 1.31 or later.

src/lib.rs

+47
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,11 @@ pub mod serde_untagged_optional;
2626

2727
use core::convert::{AsMut, AsRef};
2828
use core::fmt;
29+
use core::future::Future;
2930
use core::iter;
3031
use core::ops::Deref;
3132
use core::ops::DerefMut;
33+
use core::pin::Pin;
3234

3335
#[cfg(any(test, feature = "use_std"))]
3436
use std::error::Error;
@@ -255,6 +257,35 @@ impl<L, R> Either<L, R> {
255257
}
256258
}
257259

260+
/// Convert `Pin<&Either<L, R>>` to `Either<Pin<&L>, Pin<&R>>`,
261+
/// pinned projections of the inner variants.
262+
pub fn as_pin_ref(self: Pin<&Self>) -> Either<Pin<&L>, Pin<&R>> {
263+
// SAFETY: We can use `new_unchecked` because the `inner` parts are
264+
// guaranteed to be pinned, as they come from `self` which is pinned.
265+
unsafe {
266+
match *Pin::get_ref(self) {
267+
Left(ref inner) => Left(Pin::new_unchecked(inner)),
268+
Right(ref inner) => Right(Pin::new_unchecked(inner)),
269+
}
270+
}
271+
}
272+
273+
/// Convert `Pin<&mut Either<L, R>>` to `Either<Pin<&mut L>, Pin<&mut R>>`,
274+
/// pinned projections of the inner variants.
275+
pub fn as_pin_mut(self: Pin<&mut Self>) -> Either<Pin<&mut L>, Pin<&mut R>> {
276+
// SAFETY: `get_unchecked_mut` is fine because we don't move anything.
277+
// We can use `new_unchecked` because the `inner` parts are guaranteed
278+
// to be pinned, as they come from `self` which is pinned, and we never
279+
// offer an unpinned `&mut L` or `&mut R` through `Pin<&mut Self>`. We
280+
// also don't have an implementation of `Drop`, nor manual `Unpin`.
281+
unsafe {
282+
match *Pin::get_unchecked_mut(self) {
283+
Left(ref mut inner) => Left(Pin::new_unchecked(inner)),
284+
Right(ref mut inner) => Right(Pin::new_unchecked(inner)),
285+
}
286+
}
287+
}
288+
258289
/// Convert `Either<L, R>` to `Either<R, L>`.
259290
///
260291
/// ```
@@ -1038,6 +1069,22 @@ where
10381069
{
10391070
}
10401071

1072+
/// `Either<L, R>` is a future if both `L` and `R` are futures.
1073+
impl<L, R> Future for Either<L, R>
1074+
where
1075+
L: Future,
1076+
R: Future<Output = L::Output>,
1077+
{
1078+
type Output = L::Output;
1079+
1080+
fn poll(
1081+
self: Pin<&mut Self>,
1082+
cx: &mut core::task::Context<'_>,
1083+
) -> core::task::Poll<Self::Output> {
1084+
for_both!(self.as_pin_mut(), inner => inner.poll(cx))
1085+
}
1086+
}
1087+
10411088
#[cfg(any(test, feature = "use_std"))]
10421089
/// `Either<L, R>` implements `Read` if both `L` and `R` do.
10431090
///

0 commit comments

Comments
 (0)