use core::future::{Future, pending};
use core::pin::pin;
use core::task::{Context, Poll, Waker};
use embedded_hal_async::delay::DelayNs;
use embedded_hal_async::i2c::{ErrorType, I2c, Operation, SevenBitAddress};
pub(crate) fn poll_once_then_drop<F: Future>(future: F) -> Poll<F::Output> {
let waker = Waker::noop();
let mut context = Context::from_waker(waker);
pin!(future).as_mut().poll(&mut context)
}
pub(crate) struct PendingAt<T> {
inner: T,
pending_at: usize,
attempted: usize,
}
impl<T> PendingAt<T> {
pub(crate) const fn new(inner: T, pending_at: usize) -> Self {
Self {
inner,
pending_at,
attempted: 0,
}
}
pub(crate) fn into_inner(self) -> T {
self.inner
}
fn parks_now(&mut self) -> bool {
let parks = self.attempted == self.pending_at;
if !parks {
self.attempted += 1;
}
parks
}
}
impl<T: ErrorType> ErrorType for PendingAt<T> {
type Error = T::Error;
}
impl<T> I2c<SevenBitAddress> for PendingAt<T>
where
T: I2c<SevenBitAddress>,
{
async fn read(&mut self, address: SevenBitAddress, read: &mut [u8]) -> Result<(), Self::Error> {
if self.parks_now() {
pending::<()>().await;
}
self.inner.read(address, read).await
}
async fn write(&mut self, address: SevenBitAddress, write: &[u8]) -> Result<(), Self::Error> {
if self.parks_now() {
pending::<()>().await;
}
self.inner.write(address, write).await
}
async fn write_read(
&mut self,
address: SevenBitAddress,
write: &[u8],
read: &mut [u8],
) -> Result<(), Self::Error> {
if self.parks_now() {
pending::<()>().await;
}
self.inner.write_read(address, write, read).await
}
async fn transaction(
&mut self,
address: SevenBitAddress,
operations: &mut [Operation<'_>],
) -> Result<(), Self::Error> {
if self.parks_now() {
pending::<()>().await;
}
self.inner.transaction(address, operations).await
}
}
pub(crate) struct CancellableDelay {
parks: bool,
elapsed_ns: u64,
}
impl CancellableDelay {
pub(crate) const fn ready() -> Self {
Self {
parks: false,
elapsed_ns: 0,
}
}
pub(crate) const fn parking() -> Self {
Self {
parks: true,
elapsed_ns: 0,
}
}
pub(crate) const fn elapsed_ns(&self) -> u64 {
self.elapsed_ns
}
}
impl DelayNs for CancellableDelay {
async fn delay_ns(&mut self, ns: u32) {
if self.parks {
pending::<()>().await;
}
self.elapsed_ns += u64::from(ns);
}
}