From c8bd792b7abf3bbb0c713a07e58906e9c690a320 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Tue, 5 Apr 2022 21:17:29 +0200 Subject: reorganize `util` mod. --- embassy/src/util/mod.rs | 73 ++++-------------------------------------- embassy/src/util/select.rs | 58 +++++++++++++++++++++++++++++++++ embassy/src/util/select_all.rs | 58 --------------------------------- embassy/src/util/steal.rs | 3 ++ embassy/src/util/unborrow.rs | 60 ++++++++++++++++++++++++++++++++++ 5 files changed, 127 insertions(+), 125 deletions(-) create mode 100644 embassy/src/util/select.rs delete mode 100644 embassy/src/util/select_all.rs create mode 100644 embassy/src/util/steal.rs create mode 100644 embassy/src/util/unborrow.rs diff --git a/embassy/src/util/mod.rs b/embassy/src/util/mod.rs index f5cc96238..928edf0e2 100644 --- a/embassy/src/util/mod.rs +++ b/embassy/src/util/mod.rs @@ -1,74 +1,13 @@ //! Misc utilities mod forever; -mod select_all; +mod select; +mod steal; +mod unborrow; mod yield_now; pub use forever::*; -pub use select_all::*; +pub use select::*; +pub use steal::*; +pub use unborrow::*; pub use yield_now::*; - -/// Unsafely unborrow an owned singleton out of a `&mut`. -/// -/// It is intended to be implemented for owned peripheral singletons, such as `USART3` or `AnyPin`. -/// Unborrowing an owned `T` yields the same `T`. Unborrowing a `&mut T` yields a copy of the T. -/// -/// This allows writing HAL drivers that either own or borrow their peripherals, but that don't have -/// to store pointers in the borrowed case. -/// -/// Safety: this trait can be used to copy non-Copy types. Implementors must not cause -/// immediate UB when copied, and must not cause UB when copies are later used, provided they -/// are only used according the [`Self::unborrow`] safety contract. -/// -pub unsafe trait Unborrow { - /// Unborrow result type - type Target; - - /// Unborrow a value. - /// - /// Safety: This returns a copy of a singleton that's normally not - /// copiable. The returned copy must ONLY be used while the lifetime of `self` is - /// valid, as if it were accessed through `self` every time. - unsafe fn unborrow(self) -> Self::Target; -} - -unsafe impl<'a, T: Unborrow> Unborrow for &'a mut T { - type Target = T::Target; - unsafe fn unborrow(self) -> Self::Target { - T::unborrow(core::ptr::read(self)) - } -} - -pub trait Steal { - unsafe fn steal() -> Self; -} - -macro_rules! unsafe_impl_unborrow_tuples { - ($($t:ident),+) => { - unsafe impl<$($t),+> Unborrow for ($($t),+) - where - $( - $t: Unborrow - ),+ - { - type Target = ($($t),+); - unsafe fn unborrow(self) -> Self::Target { - self - } - } - - - }; -} - -unsafe_impl_unborrow_tuples!(A, B); -unsafe_impl_unborrow_tuples!(A, B, C); -unsafe_impl_unborrow_tuples!(A, B, C, D); -unsafe_impl_unborrow_tuples!(A, B, C, D, E); -unsafe_impl_unborrow_tuples!(A, B, C, D, E, F); -unsafe_impl_unborrow_tuples!(A, B, C, D, E, F, G); -unsafe_impl_unborrow_tuples!(A, B, C, D, E, F, G, H); -unsafe_impl_unborrow_tuples!(A, B, C, D, E, F, G, H, I); -unsafe_impl_unborrow_tuples!(A, B, C, D, E, F, G, H, I, J); -unsafe_impl_unborrow_tuples!(A, B, C, D, E, F, G, H, I, J, K); -unsafe_impl_unborrow_tuples!(A, B, C, D, E, F, G, H, I, J, K, L); diff --git a/embassy/src/util/select.rs b/embassy/src/util/select.rs new file mode 100644 index 000000000..aef22d894 --- /dev/null +++ b/embassy/src/util/select.rs @@ -0,0 +1,58 @@ +use core::future::Future; +use core::pin::Pin; +use core::task::{Context, Poll}; + +/// Future for the [`select_all`] function. +#[derive(Debug)] +#[must_use = "futures do nothing unless you `.await` or poll them"] +pub struct SelectAll { + inner: [Fut; N], +} + +impl Unpin for SelectAll {} + +/// Creates a new future which will select over a list of futures. +/// +/// The returned future will wait for any future within `iter` to be ready. Upon +/// completion the item resolved will be returned, along with the index of the +/// future that was ready. +/// +/// # Panics +/// +/// This function will panic if the array specified contains no items. +pub fn select_all(arr: [Fut; N]) -> SelectAll { + assert!(N > 0); + SelectAll { inner: arr } +} + +impl SelectAll { + /// Consumes this combinator, returning the underlying futures. + pub fn into_inner(self) -> [Fut; N] { + self.inner + } +} + +impl Future for SelectAll { + type Output = (Fut::Output, usize); + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + // Safety: Since `self` is pinned, `inner` cannot move. Since `inner` cannot move, + // its elements also cannot move. Therefore it is safe to access `inner` and pin + // references to the contained futures. + let item = unsafe { + self.get_unchecked_mut() + .inner + .iter_mut() + .enumerate() + .find_map(|(i, f)| match Pin::new_unchecked(f).poll(cx) { + Poll::Pending => None, + Poll::Ready(e) => Some((i, e)), + }) + }; + + match item { + Some((idx, res)) => Poll::Ready((res, idx)), + None => Poll::Pending, + } + } +} diff --git a/embassy/src/util/select_all.rs b/embassy/src/util/select_all.rs deleted file mode 100644 index aef22d894..000000000 --- a/embassy/src/util/select_all.rs +++ /dev/null @@ -1,58 +0,0 @@ -use core::future::Future; -use core::pin::Pin; -use core::task::{Context, Poll}; - -/// Future for the [`select_all`] function. -#[derive(Debug)] -#[must_use = "futures do nothing unless you `.await` or poll them"] -pub struct SelectAll { - inner: [Fut; N], -} - -impl Unpin for SelectAll {} - -/// Creates a new future which will select over a list of futures. -/// -/// The returned future will wait for any future within `iter` to be ready. Upon -/// completion the item resolved will be returned, along with the index of the -/// future that was ready. -/// -/// # Panics -/// -/// This function will panic if the array specified contains no items. -pub fn select_all(arr: [Fut; N]) -> SelectAll { - assert!(N > 0); - SelectAll { inner: arr } -} - -impl SelectAll { - /// Consumes this combinator, returning the underlying futures. - pub fn into_inner(self) -> [Fut; N] { - self.inner - } -} - -impl Future for SelectAll { - type Output = (Fut::Output, usize); - - fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { - // Safety: Since `self` is pinned, `inner` cannot move. Since `inner` cannot move, - // its elements also cannot move. Therefore it is safe to access `inner` and pin - // references to the contained futures. - let item = unsafe { - self.get_unchecked_mut() - .inner - .iter_mut() - .enumerate() - .find_map(|(i, f)| match Pin::new_unchecked(f).poll(cx) { - Poll::Pending => None, - Poll::Ready(e) => Some((i, e)), - }) - }; - - match item { - Some((idx, res)) => Poll::Ready((res, idx)), - None => Poll::Pending, - } - } -} diff --git a/embassy/src/util/steal.rs b/embassy/src/util/steal.rs new file mode 100644 index 000000000..a0d5f1359 --- /dev/null +++ b/embassy/src/util/steal.rs @@ -0,0 +1,3 @@ +pub trait Steal { + unsafe fn steal() -> Self; +} diff --git a/embassy/src/util/unborrow.rs b/embassy/src/util/unborrow.rs new file mode 100644 index 000000000..dacfa3d42 --- /dev/null +++ b/embassy/src/util/unborrow.rs @@ -0,0 +1,60 @@ +/// Unsafely unborrow an owned singleton out of a `&mut`. +/// +/// It is intended to be implemented for owned peripheral singletons, such as `USART3` or `AnyPin`. +/// Unborrowing an owned `T` yields the same `T`. Unborrowing a `&mut T` yields a copy of the T. +/// +/// This allows writing HAL drivers that either own or borrow their peripherals, but that don't have +/// to store pointers in the borrowed case. +/// +/// Safety: this trait can be used to copy non-Copy types. Implementors must not cause +/// immediate UB when copied, and must not cause UB when copies are later used, provided they +/// are only used according the [`Self::unborrow`] safety contract. +/// +pub unsafe trait Unborrow { + /// Unborrow result type + type Target; + + /// Unborrow a value. + /// + /// Safety: This returns a copy of a singleton that's normally not + /// copiable. The returned copy must ONLY be used while the lifetime of `self` is + /// valid, as if it were accessed through `self` every time. + unsafe fn unborrow(self) -> Self::Target; +} + +unsafe impl<'a, T: Unborrow> Unborrow for &'a mut T { + type Target = T::Target; + unsafe fn unborrow(self) -> Self::Target { + T::unborrow(core::ptr::read(self)) + } +} + +macro_rules! unsafe_impl_unborrow_tuples { + ($($t:ident),+) => { + unsafe impl<$($t),+> Unborrow for ($($t),+) + where + $( + $t: Unborrow + ),+ + { + type Target = ($($t),+); + unsafe fn unborrow(self) -> Self::Target { + self + } + } + + + }; +} + +unsafe_impl_unborrow_tuples!(A, B); +unsafe_impl_unborrow_tuples!(A, B, C); +unsafe_impl_unborrow_tuples!(A, B, C, D); +unsafe_impl_unborrow_tuples!(A, B, C, D, E); +unsafe_impl_unborrow_tuples!(A, B, C, D, E, F); +unsafe_impl_unborrow_tuples!(A, B, C, D, E, F, G); +unsafe_impl_unborrow_tuples!(A, B, C, D, E, F, G, H); +unsafe_impl_unborrow_tuples!(A, B, C, D, E, F, G, H, I); +unsafe_impl_unborrow_tuples!(A, B, C, D, E, F, G, H, I, J); +unsafe_impl_unborrow_tuples!(A, B, C, D, E, F, G, H, I, J, K); +unsafe_impl_unborrow_tuples!(A, B, C, D, E, F, G, H, I, J, K, L); -- cgit