summaryrefslogtreecommitdiff
path: root/embassy-hal-common
diff options
context:
space:
mode:
authorGrant Miller <GrantM11235@gmail.com>2022-07-03 16:16:10 -0500
committerDario Nieuwenhuis <dirbaio@dirbaio.net>2022-07-23 01:33:22 +0200
commit65a82d02d17fc491246eae219f416e565719c0ac (patch)
tree1d4842d73031529f018d6b96a84c090e0fb3eb82 /embassy-hal-common
parentffbd9363f2a52fd27c81bbfbbe8e0e605a1ece86 (diff)
downloadembassy-65a82d02d17fc491246eae219f416e565719c0ac.zip
WIP: Make unborrow safe to use
Diffstat (limited to 'embassy-hal-common')
-rw-r--r--embassy-hal-common/src/lib.rs2
-rw-r--r--embassy-hal-common/src/macros.rs16
-rw-r--r--embassy-hal-common/src/unborrow.rs79
3 files changed, 80 insertions, 17 deletions
diff --git a/embassy-hal-common/src/lib.rs b/embassy-hal-common/src/lib.rs
index c8cf1c4c..da7ae991 100644
--- a/embassy-hal-common/src/lib.rs
+++ b/embassy-hal-common/src/lib.rs
@@ -9,7 +9,7 @@ mod macros;
pub mod ratio;
pub mod ring_buffer;
mod unborrow;
-pub use unborrow::Unborrow;
+pub use unborrow::{Unborrow, Unborrowed};
/// Low power blocking wait loop using WFE/SEV.
pub fn low_power_wait_until(mut condition: impl FnMut() -> bool) {
diff --git a/embassy-hal-common/src/macros.rs b/embassy-hal-common/src/macros.rs
index ffa5e4fb..d693308b 100644
--- a/embassy-hal-common/src/macros.rs
+++ b/embassy-hal-common/src/macros.rs
@@ -24,8 +24,11 @@ macro_rules! peripherals {
unsafe impl $crate::Unborrow for $name {
type Target = $name;
#[inline]
- unsafe fn unborrow(self) -> $name {
- self
+ fn unborrow<'a>(self) -> $crate::Unborrowed<'a, Self::Target>
+ where
+ Self: 'a,
+ {
+ $crate::Unborrowed::new(self)
}
}
)*
@@ -80,7 +83,7 @@ macro_rules! peripherals {
macro_rules! unborrow {
($($name:ident),*) => {
$(
- let mut $name = unsafe { $name.unborrow() };
+ let mut $name = $name.unborrow();
)*
}
}
@@ -91,8 +94,11 @@ macro_rules! unsafe_impl_unborrow {
unsafe impl $crate::Unborrow for $type {
type Target = $type;
#[inline]
- unsafe fn unborrow(self) -> Self::Target {
- self
+ fn unborrow<'a>(self) -> $crate::Unborrowed<'a, Self::Target>
+ where
+ Self: 'a,
+ {
+ $crate::Unborrowed::new(self)
}
}
};
diff --git a/embassy-hal-common/src/unborrow.rs b/embassy-hal-common/src/unborrow.rs
index dacfa3d4..c05a070c 100644
--- a/embassy-hal-common/src/unborrow.rs
+++ b/embassy-hal-common/src/unborrow.rs
@@ -1,7 +1,45 @@
+use core::marker::PhantomData;
+use core::ops::{Deref, DerefMut};
+
+/// This is essentially a `&mut T`, but it is the size of `T` not the size
+/// of a pointer. This is useful if T is a zero sized type.
+pub struct Unborrowed<'a, T> {
+ inner: T,
+ _lifetime: PhantomData<&'a mut T>,
+}
+
+impl<'a, T> Unborrowed<'a, T> {
+ pub fn new(inner: T) -> Self {
+ Self {
+ inner,
+ _lifetime: PhantomData,
+ }
+ }
+
+ pub unsafe fn into_inner(self) -> T {
+ self.inner
+ }
+}
+
+impl<'a, T> Deref for Unborrowed<'a, T> {
+ type Target = T;
+
+ fn deref(&self) -> &Self::Target {
+ &self.inner
+ }
+}
+
+impl<'a, T> DerefMut for Unborrowed<'a, T> {
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ &mut self.inner
+ }
+}
+
/// 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.
+/// Unborrowing an owned `T` yields an `Unborrowed<'static, T>`.
+/// Unborrowing a `&'a mut T` yields an `Unborrowed<'a, 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.
@@ -15,17 +53,33 @@ pub unsafe trait Unborrow {
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;
+ fn unborrow<'a>(self) -> Unborrowed<'a, Self::Target>
+ where
+ Self: 'a;
}
-unsafe impl<'a, T: Unborrow> Unborrow for &'a mut T {
+unsafe impl<'b, T: Unborrow> Unborrow for &'b mut T {
type Target = T::Target;
- unsafe fn unborrow(self) -> Self::Target {
- T::unborrow(core::ptr::read(self))
+
+ fn unborrow<'a>(self) -> Unborrowed<'a, Self::Target>
+ where
+ Self: 'a,
+ {
+ // 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.
+ T::unborrow(unsafe { core::ptr::read(self) })
+ }
+}
+
+unsafe impl<'b, T> Unborrow for Unborrowed<'b, T> {
+ type Target = T;
+
+ fn unborrow<'a>(self) -> Unborrowed<'a, Self::Target>
+ where
+ Self: 'a,
+ {
+ self
}
}
@@ -38,8 +92,11 @@ macro_rules! unsafe_impl_unborrow_tuples {
),+
{
type Target = ($($t),+);
- unsafe fn unborrow(self) -> Self::Target {
- self
+ fn unborrow<'a>(self) -> Unborrowed<'a, Self::Target>
+ where
+ Self: 'a
+ {
+ Unborrowed::new(self)
}
}