async/spi: make helpers default methods instead of an extension trait.

It turns out you *can* have default methods on a GAT-based async trait. All
you have to do is move the TAITs out of the trait so Rust infers them
instead of the impl specifying them.

Impls can't override the methods, but they already couldn't before with
the extension trait.

This makes async SpiDevice more consistent with blocking, and makes the helpers
more discoverable.
This commit is contained in:
Dario Nieuwenhuis
2022-05-03 23:54:02 +02:00
parent 58587e8de0
commit 14103be039

View File

@@ -7,6 +7,34 @@ pub use embedded_hal::spi::{
};
use embedded_hal::{digital::blocking::OutputPin, spi::blocking};
type ReadFuture<'a, T, Word>
where
T: SpiDevice + ?Sized + 'a,
T::Bus: SpiBusRead<Word>,
Word: Copy + 'static,
= impl Future<Output = Result<(), T::Error>>;
type WriteFuture<'a, T, Word>
where
T: SpiDevice + ?Sized + 'a,
T::Bus: SpiBusWrite<Word>,
Word: Copy + 'static,
= impl Future<Output = Result<(), T::Error>>;
type TransferFuture<'a, T, Word>
where
T: SpiDevice + ?Sized + 'a,
T::Bus: SpiBus<Word>,
Word: Copy + 'static,
= impl Future<Output = Result<(), T::Error>>;
type TransferInPlaceFuture<'a, T, Word>
where
T: SpiDevice + ?Sized + 'a,
T::Bus: SpiBus<Word>,
Word: Copy + 'static,
= impl Future<Output = Result<(), T::Error>>;
/// SPI device trait
///
/// `SpiDevice` represents ownership over a single SPI device on a (possibly shared) bus, selected
@@ -45,97 +73,13 @@ pub trait SpiDevice: ErrorType {
where
F: FnOnce(*mut Self::Bus) -> Fut + 'a,
Fut: Future<Output = Result<R, <Self::Bus as ErrorType>::Error>> + 'a;
}
/// Helper methods for SpiDevice.
///
/// This is automatically implemented for all `T: SpiDevice`, you can directly
/// use the methods on any `SpiDevice`.
pub trait SpiDeviceExt: SpiDevice {
/// Future returned by the `read` method.
type ReadFuture<'a, Word>: Future<Output = Result<(), Self::Error>> + 'a
where
Self: 'a,
Self::Bus: SpiBusRead<Word>,
Word: Copy + 'static;
/// Do a read within a transaction.
///
/// This is a convenience method equivalent to `device.transaction(|bus| bus.read(buf))`.
///
/// See also: [`SpiDevice::transaction`], [`SpiBusRead::read`]
fn read<'a, Word>(&'a mut self, buf: &'a mut [Word]) -> Self::ReadFuture<'a, Word>
where
Self::Bus: SpiBusRead<Word>,
Word: Copy + 'static;
/// Future returned by the `write` method.
type WriteFuture<'a, Word>: Future<Output = Result<(), Self::Error>> + 'a
where
Self: 'a,
Self::Bus: SpiBusWrite<Word>,
Word: Copy + 'static;
/// Do a write within a transaction.
///
/// This is a convenience method equivalent to `device.transaction(|bus| bus.write(buf))`.
///
/// See also: [`SpiDevice::transaction`], [`SpiBusWrite::write`]
fn write<'a, Word>(&'a mut self, buf: &'a [Word]) -> Self::WriteFuture<'a, Word>
where
Self::Bus: SpiBusWrite<Word>,
Word: Copy + 'static;
/// Future returned by the `transfer` method.
type TransferFuture<'a, Word>: Future<Output = Result<(), Self::Error>> + 'a
where
Self: 'a,
Self::Bus: SpiBus<Word>,
Word: Copy + 'static;
/// Do a transfer within a transaction.
///
/// This is a convenience method equivalent to `device.transaction(|bus| bus.transfer(read, write))`.
///
/// See also: [`SpiDevice::transaction`], [`SpiBus::transfer`]
fn transfer<'a, Word>(
&'a mut self,
read: &'a mut [Word],
write: &'a [Word],
) -> Self::TransferFuture<'a, Word>
where
Self::Bus: SpiBus<Word>,
Word: Copy + 'static;
/// Future returned by the `transfer_in_place` method.
type TransferInPlaceFuture<'a, Word>: Future<Output = Result<(), Self::Error>> + 'a
where
Self: 'a,
Self::Bus: SpiBus<Word>,
Word: Copy + 'static;
/// Do an in-place transfer within a transaction.
///
/// This is a convenience method equivalent to `device.transaction(|bus| bus.transfer_in_place(buf))`.
///
/// See also: [`SpiDevice::transaction`], [`SpiBus::transfer_in_place`]
fn transfer_in_place<'a, Word>(
&'a mut self,
buf: &'a mut [Word],
) -> Self::TransferInPlaceFuture<'a, Word>
where
Self::Bus: SpiBus<Word>,
Word: Copy + 'static;
}
impl<T: SpiDevice> SpiDeviceExt for T {
type ReadFuture<'a, Word> = impl Future<Output = Result<(), Self::Error>> + 'a
where
Self: 'a,
Self::Bus: SpiBusRead<Word>,
Word: Copy + 'static;
fn read<'a, Word>(&'a mut self, buf: &'a mut [Word]) -> Self::ReadFuture<'a, Word>
fn read<'a, Word>(&'a mut self, buf: &'a mut [Word]) -> ReadFuture<'a, Self, Word>
where
Self::Bus: SpiBusRead<Word>,
Word: Copy + 'static,
@@ -147,13 +91,12 @@ impl<T: SpiDevice> SpiDeviceExt for T {
})
}
type WriteFuture<'a, Word> = impl Future<Output = Result<(), Self::Error>> + 'a
where
Self: 'a,
Self::Bus: SpiBusWrite<Word>,
Word: Copy + 'static;
fn write<'a, Word>(&'a mut self, buf: &'a [Word]) -> Self::WriteFuture<'a, Word>
/// Do a write within a transaction.
///
/// This is a convenience method equivalent to `device.transaction(|bus| bus.write(buf))`.
///
/// See also: [`SpiDevice::transaction`], [`SpiBusWrite::write`]
fn write<'a, Word>(&'a mut self, buf: &'a [Word]) -> WriteFuture<'a, Self, Word>
where
Self::Bus: SpiBusWrite<Word>,
Word: Copy + 'static,
@@ -165,17 +108,16 @@ impl<T: SpiDevice> SpiDeviceExt for T {
})
}
type TransferFuture<'a, Word> = impl Future<Output = Result<(), Self::Error>> + 'a
where
Self: 'a,
Self::Bus: SpiBus<Word>,
Word: Copy + 'static;
/// Do a transfer within a transaction.
///
/// This is a convenience method equivalent to `device.transaction(|bus| bus.transfer(read, write))`.
///
/// See also: [`SpiDevice::transaction`], [`SpiBus::transfer`]
fn transfer<'a, Word>(
&'a mut self,
read: &'a mut [Word],
write: &'a [Word],
) -> Self::TransferFuture<'a, Word>
) -> TransferFuture<'a, Self, Word>
where
Self::Bus: SpiBus<Word>,
Word: Copy + 'static,
@@ -187,16 +129,15 @@ impl<T: SpiDevice> SpiDeviceExt for T {
})
}
type TransferInPlaceFuture<'a, Word> = impl Future<Output = Result<(), Self::Error>> + 'a
where
Self: 'a,
Self::Bus: SpiBus<Word>,
Word: Copy + 'static;
/// Do an in-place transfer within a transaction.
///
/// This is a convenience method equivalent to `device.transaction(|bus| bus.transfer_in_place(buf))`.
///
/// See also: [`SpiDevice::transaction`], [`SpiBus::transfer_in_place`]
fn transfer_in_place<'a, Word>(
&'a mut self,
buf: &'a mut [Word],
) -> Self::TransferInPlaceFuture<'a, Word>
) -> TransferInPlaceFuture<'a, Self, Word>
where
Self::Bus: SpiBus<Word>,
Word: Copy + 'static,