WIP: Make unborrow safe to use
This commit is contained in:
committed by
Dario Nieuwenhuis
parent
ffbd9363f2
commit
65a82d02d1
@ -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) {
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user