-
Notifications
You must be signed in to change notification settings - Fork 48
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Co-authored-by: Adin Ackerman <[email protected]>
- Loading branch information
Showing
5 changed files
with
160 additions
and
47 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
use crate::Sealed; | ||
use core::marker::PhantomData; | ||
|
||
pub trait IntoObservationToken: Sized + crate::Sealed { | ||
type Peripheral; | ||
fn into_ot(self) -> ObservationToken<Self::Peripheral>; | ||
} | ||
|
||
/// A struct to hold peripherals which are to be observed. | ||
/// | ||
/// This prevents the observed peripheral from being consumed. Thus | ||
/// preventing things like a an observed gpio pin changing mode or an opamp from | ||
/// being disabled. This makes sure the underlaying peripheral will not | ||
/// change mode into something that is not compatible with what ever may be observing it. | ||
pub struct Observed<P, const OBSERVER_COUNT: usize> { | ||
peripheral: P, | ||
} | ||
|
||
impl<P, const OBSERVER_COUNT: usize> Observed<P, OBSERVER_COUNT> { | ||
/// Release the observation of this peripheral | ||
/// | ||
/// This returns the underlaying perpheral type. Since it is no longer | ||
/// observed, you are once again free to do what you want with it. | ||
pub fn release(self, _data: [ObservationToken<P>; OBSERVER_COUNT]) -> P { | ||
self.peripheral | ||
} | ||
} | ||
|
||
/// A struct to represent a registered observation of a peripheral of type `P` | ||
/// | ||
/// The existence of this type guarantees that the observed peripheral will not | ||
/// change mode into something that is not compatibe with what ever is observing it | ||
pub struct ObservationToken<P> { | ||
_p: PhantomData<P>, | ||
} | ||
|
||
/// A trait providing an interface to make peripherals observed | ||
/// | ||
/// See [`Observed`] and [`ObservationToken`] | ||
pub trait Observable: Sized { | ||
fn observe<const N: usize>(self) -> (Observed<Self, N>, [ObservationToken<Self>; N]) { | ||
( | ||
Observed { peripheral: self }, | ||
core::array::from_fn(|_| ObservationToken { _p: PhantomData }), | ||
) | ||
} | ||
} | ||
|
||
impl<P: Observable + Sealed> IntoObservationToken for P { | ||
type Peripheral = P; | ||
fn into_ot(self) -> ObservationToken<Self::Peripheral> { | ||
let (_peripheral, [ot]) = self.observe(); | ||
ot | ||
} | ||
} | ||
|
||
impl<P: Observable + Sealed> Sealed for ObservationToken<P> {} | ||
impl<P: Observable + Sealed> IntoObservationToken for ObservationToken<P> { | ||
type Peripheral = P; | ||
fn into_ot(self) -> Self { | ||
self | ||
} | ||
} | ||
|
||
impl<P, const N: usize> AsRef<P> for Observed<P, N> { | ||
fn as_ref(&self) -> &P { | ||
&self.peripheral | ||
} | ||
} | ||
|
||
impl<P, const N: usize> AsMut<P> for Observed<P, N> { | ||
fn as_mut(&mut self) -> &mut P { | ||
&mut self.peripheral | ||
} | ||
} |