Skip to content

Commit

Permalink
impl Future for combinator Either*
Browse files Browse the repository at this point in the history
  • Loading branch information
GlenDC committed Nov 7, 2024
1 parent 5efa6e7 commit 03cb4eb
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 3 deletions.
1 change: 0 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,6 @@ flume = "0.11.1"
[workspace.lints.rust]
unreachable_pub = "deny"
elided_lifetimes_in_paths = "allow"
unsafe_code = "forbid"

[workspace.lints.clippy]
all = { level = "warn", priority = -1 }
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,8 @@ let info: Info = client
## ⛨ | Safety
This crate uses `#![forbid(unsafe_code)]` to ensure everything is implemented in 100% safe Rust.
The rama crates avoid `unsafe_code`, but do make use of it for some low level primitives (e.g. http core)
or indirectly because of bindgens to C (e.g. boring).
We also make use of [`cargo vet`](https://github.com/mozilla/cargo-vet) to [audit our supply chain](./supply-chain/).
Expand Down
3 changes: 2 additions & 1 deletion docs/book/src/crate.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ to know how to use rama for your purposes.

## ⛨ | Safety

This crate uses `#![forbid(unsafe_code)]` to ensure everything is implemented in 100% safe Rust.
The rama crates avoid `unsafe_code`, but do make use of it for some low level primitives (e.g. http core)
or indirectly because of bindgens to C (e.g. boring).

We also make use of [`cargo vet`](https://github.com/mozilla/cargo-vet) to
[audit our supply chain](https://github.com/plabayo/rama/tree/main/supply-chain/).
Expand Down
38 changes: 38 additions & 0 deletions rama-core/src/combinators/either.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,44 @@ macro_rules! define_either {
}
}
}


impl<$($param),+, Output> $id<$($param),+>
where
$($param: std::future::Future<Output = Output>),+
{
/// Convert `Pin<&mut Either<A, B>>` to `Either<Pin<&mut A>, Pin<&mut B>>`,
/// pinned projections of the inner variants.
fn as_pin_mut(self: Pin<&mut Self>) -> $id<$(Pin<&mut $param>),+> {
// SAFETY: `get_unchecked_mut` is fine because we don't move anything.
// We can use `new_unchecked` because the `inner` parts are guaranteed
// to be pinned, as they come from `self` which is pinned, and we never
// offer an unpinned `&mut A` or `&mut B` through `Pin<&mut Self>`. We
// also don't have an implementation of `Drop`, nor manual `Unpin`.
unsafe {
match self.get_unchecked_mut() {
$(
Self::$param(inner) => $id::$param(Pin::new_unchecked(inner)),
)+
}
}
}
}

impl<$($param),+, Output> std::future::Future for $id<$($param),+>
where
$($param: std::future::Future<Output = Output> + Unpin),+
{
type Output = Output;

fn poll(self: Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> Poll<Self::Output> {
match self.as_pin_mut() {
$(
$id::$param(fut) => fut.poll(cx),
)+
}
}
}
};
}

Expand Down

0 comments on commit 03cb4eb

Please sign in to comment.