From 14103be0394a5dc53b9dca738f0771f5151bfca0 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Tue, 3 May 2022 23:54:02 +0200 Subject: [PATCH] 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. --- embedded-hal-async/src/spi.rs | 153 +++++++++++----------------------- 1 file changed, 47 insertions(+), 106 deletions(-) diff --git a/embedded-hal-async/src/spi.rs b/embedded-hal-async/src/spi.rs index ec79433..6eb2bfc 100644 --- a/embedded-hal-async/src/spi.rs +++ b/embedded-hal-async/src/spi.rs @@ -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: Copy + 'static, += impl Future>; + +type WriteFuture<'a, T, Word> +where + T: SpiDevice + ?Sized + 'a, + T::Bus: SpiBusWrite, + Word: Copy + 'static, += impl Future>; + +type TransferFuture<'a, T, Word> +where + T: SpiDevice + ?Sized + 'a, + T::Bus: SpiBus, + Word: Copy + 'static, += impl Future>; + +type TransferInPlaceFuture<'a, T, Word> +where + T: SpiDevice + ?Sized + 'a, + T::Bus: SpiBus, + Word: Copy + 'static, += impl Future>; + /// 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::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> + 'a - where - Self: 'a, - Self::Bus: SpiBusRead, - 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: Copy + 'static; - - /// Future returned by the `write` method. - type WriteFuture<'a, Word>: Future> + 'a - where - Self: 'a, - Self::Bus: SpiBusWrite, - 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: Copy + 'static; - - /// Future returned by the `transfer` method. - type TransferFuture<'a, Word>: Future> + 'a - where - Self: 'a, - Self::Bus: SpiBus, - 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: Copy + 'static; - - /// Future returned by the `transfer_in_place` method. - type TransferInPlaceFuture<'a, Word>: Future> + 'a - where - Self: 'a, - Self::Bus: SpiBus, - 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: Copy + 'static; -} - -impl SpiDeviceExt for T { - type ReadFuture<'a, Word> = impl Future> + 'a - where - Self: 'a, - Self::Bus: SpiBusRead, - 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: Copy + 'static, @@ -147,13 +91,12 @@ impl SpiDeviceExt for T { }) } - type WriteFuture<'a, Word> = impl Future> + 'a - where - Self: 'a, - Self::Bus: SpiBusWrite, - 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: Copy + 'static, @@ -165,17 +108,16 @@ impl SpiDeviceExt for T { }) } - type TransferFuture<'a, Word> = impl Future> + 'a - where - Self: 'a, - Self::Bus: SpiBus, - 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: Copy + 'static, @@ -187,16 +129,15 @@ impl SpiDeviceExt for T { }) } - type TransferInPlaceFuture<'a, Word> = impl Future> + 'a - where - Self: 'a, - Self::Bus: SpiBus, - 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: Copy + 'static,