use core::future::Future; use core::marker::PhantomData; use core::pin::Pin; use core::task::{Context, Poll}; use embassy::blocking_mutex::raw::RawMutex; use embassy::channel::Channel; #[derive(Debug, Clone)] pub enum Either3 { First(A), Second(B), Third(C), } /// Same as [`select`], but with more futures. pub fn select3(a: A, b: B, c: C) -> Select3 where A: Future, B: Future, C: Future, { Select3 { a, b, c } } /// Future for the [`select3`] function. #[derive(Debug)] #[must_use = "futures do nothing unless you `.await` or poll them"] pub struct Select3 { a: A, b: B, c: C, } impl Future for Select3 where A: Future, B: Future, C: Future, { type Output = Either3; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let this = unsafe { self.get_unchecked_mut() }; let a = unsafe { Pin::new_unchecked(&mut this.a) }; let b = unsafe { Pin::new_unchecked(&mut this.b) }; let c = unsafe { Pin::new_unchecked(&mut this.c) }; if let Poll::Ready(x) = a.poll(cx) { return Poll::Ready(Either3::First(x)); } if let Poll::Ready(x) = b.poll(cx) { return Poll::Ready(Either3::Second(x)); } if let Poll::Ready(x) = c.poll(cx) { return Poll::Ready(Either3::Third(x)); } Poll::Pending } } pub struct Pending { _phantom: PhantomData, } impl Pending { fn new() -> Self { Pending { _phantom: PhantomData, } } } impl Future for Pending { type Output = T; fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll { Poll::Pending } } pub async fn recv_or_wait(ch: Option<&Channel>) -> T { match ch { Some(ch) => ch.recv().await, None => Pending::new().await, } }