use core::marker::PhantomData;
pub struct Forward<T, M = ()> {
inner: T,
_marker: PhantomData<M>,
}
pub trait ForwardCompat<T, M = ()> {
fn forward(self) -> Forward<T, M>;
}
impl<T, M> ForwardCompat<T, M> for T {
fn forward(self) -> Forward<T, M> {
Forward::new(self)
}
}
impl<T, M> Forward<T, M> {
pub fn new(inner: T) -> Forward<T, M> {
Forward {
inner,
_marker: PhantomData,
}
}
pub fn inner(&self) -> &T {
&self.inner
}
pub fn inner_mut(&mut self) -> &mut T {
&mut self.inner
}
pub fn unwrap(self) -> T {
self.inner
}
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "defmt-03", derive(defmt::Format))]
pub struct ForwardError<E>(pub E);
mod digital {
use super::{Forward, ForwardError};
use crate::markers::{ForwardInputPin, ForwardIoPin, ForwardOutputPin};
impl<E: core::fmt::Debug> eh1_0::digital::Error for ForwardError<E> {
fn kind(&self) -> eh1_0::digital::ErrorKind {
eh1_0::digital::ErrorKind::Other
}
}
impl<T, E> eh1_0::digital::ErrorType for Forward<T, ForwardInputPin>
where
T: eh0_2::digital::v2::InputPin<Error = E>,
E: core::fmt::Debug,
{
type Error = super::ForwardError<E>;
}
impl<T, E> eh1_0::digital::InputPin for Forward<T, ForwardInputPin>
where
T: eh0_2::digital::v2::InputPin<Error = E>,
E: core::fmt::Debug,
{
fn is_high(&mut self) -> Result<bool, Self::Error> {
self.inner.is_high().map_err(ForwardError)
}
fn is_low(&mut self) -> Result<bool, Self::Error> {
self.inner.is_low().map_err(ForwardError)
}
}
impl<T, E> eh1_0::digital::ErrorType for Forward<T, ForwardOutputPin>
where
T: eh0_2::digital::v2::OutputPin<Error = E>,
E: core::fmt::Debug,
{
type Error = super::ForwardError<E>;
}
impl<T, E> eh1_0::digital::OutputPin for Forward<T, ForwardOutputPin>
where
T: eh0_2::digital::v2::OutputPin<Error = E>,
E: core::fmt::Debug,
{
fn set_high(&mut self) -> Result<(), Self::Error> {
self.inner.set_high().map_err(ForwardError)
}
fn set_low(&mut self) -> Result<(), Self::Error> {
self.inner.set_low().map_err(ForwardError)
}
}
impl<T, E> eh1_0::digital::ErrorType for Forward<T, ForwardIoPin>
where
T: eh0_2::digital::v2::OutputPin<Error = E> + eh0_2::digital::v2::InputPin<Error = E>,
E: core::fmt::Debug,
{
type Error = super::ForwardError<E>;
}
impl<T, E> eh1_0::digital::InputPin for Forward<T, ForwardIoPin>
where
T: eh0_2::digital::v2::InputPin<Error = E> + eh0_2::digital::v2::OutputPin<Error = E>,
E: core::fmt::Debug,
{
fn is_high(&mut self) -> Result<bool, Self::Error> {
self.inner.is_high().map_err(ForwardError)
}
fn is_low(&mut self) -> Result<bool, Self::Error> {
self.inner.is_low().map_err(ForwardError)
}
}
impl<T, E> eh1_0::digital::OutputPin for Forward<T, ForwardIoPin>
where
T: eh0_2::digital::v2::InputPin<Error = E> + eh0_2::digital::v2::OutputPin<Error = E>,
E: core::fmt::Debug,
{
fn set_high(&mut self) -> Result<(), Self::Error> {
self.inner.set_high().map_err(ForwardError)
}
fn set_low(&mut self) -> Result<(), Self::Error> {
self.inner.set_low().map_err(ForwardError)
}
}
}
mod delay {
use super::Forward;
impl<T> eh1_0::delay::DelayNs for Forward<T>
where
T: eh0_2::blocking::delay::DelayUs<u32>,
{
fn delay_ns(&mut self, ns: u32) {
self.inner.delay_us(ns.div_ceil(1000))
}
fn delay_us(&mut self, us: u32) {
self.inner.delay_us(us)
}
}
}
mod spi {
use super::{Forward, ForwardError};
impl<E: core::fmt::Debug> eh1_0::spi::Error for ForwardError<E> {
fn kind(&self) -> eh1_0::spi::ErrorKind {
eh1_0::spi::ErrorKind::Other
}
}
impl<T, E> eh1_0::spi::ErrorType for Forward<T>
where
T: eh0_2::blocking::spi::Transfer<u8, Error = E>,
E: core::fmt::Debug,
{
type Error = ForwardError<E>;
}
impl<T, E> eh1_0::spi::SpiBus<u8> for Forward<T>
where
T: eh0_2::blocking::spi::Transfer<u8, Error = E>
+ eh0_2::blocking::spi::Write<u8, Error = E>,
E: core::fmt::Debug,
{
fn read(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
for word in words.iter_mut() {
*word = 0x00;
}
self.inner.transfer(words).map_err(ForwardError)?;
Ok(())
}
fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> {
self.inner.write(words).map_err(ForwardError)
}
fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Self::Error> {
read.copy_from_slice(&write[..read.len()]);
self.inner.transfer(read).map_err(ForwardError)?;
Ok(())
}
fn transfer_in_place(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
self.inner.transfer(words).map_err(ForwardError)?;
Ok(())
}
fn flush(&mut self) -> Result<(), Self::Error> {
Ok(())
}
}
}
mod i2c {
use super::{Forward, ForwardError};
use eh1_0::i2c::SevenBitAddress;
use eh0_2::blocking::i2c::{self as eh0_2_i2c};
impl<E: core::fmt::Debug> eh1_0::i2c::Error for ForwardError<E> {
fn kind(&self) -> eh1_0::i2c::ErrorKind {
eh1_0::i2c::ErrorKind::Other
}
}
impl<T, E> eh1_0::i2c::ErrorType for Forward<T>
where
T: eh0_2::blocking::i2c::Read<Error = E>,
E: core::fmt::Debug,
{
type Error = ForwardError<E>;
}
impl<T, E> eh1_0::i2c::I2c<SevenBitAddress> for Forward<T>
where
T: eh0_2_i2c::Write<Error = E>
+ eh0_2_i2c::WriteIter<Error = E>
+ eh0_2_i2c::Read<Error = E>
+ eh0_2_i2c::WriteRead<Error = E>
+ eh0_2_i2c::WriteIterRead<Error = E>
+ eh0_2_i2c::Transactional<Error = E>
+ eh0_2_i2c::TransactionalIter<Error = E>,
E: core::fmt::Debug,
{
fn read(&mut self, address: SevenBitAddress, words: &mut [u8]) -> Result<(), Self::Error> {
self.inner.read(address, words).map_err(ForwardError)
}
fn write(&mut self, address: SevenBitAddress, words: &[u8]) -> Result<(), Self::Error> {
eh0_2_i2c::Write::write(&mut self.inner, address, words).map_err(ForwardError)
}
fn write_read(
&mut self,
address: SevenBitAddress,
bytes: &[u8],
buffer: &mut [u8],
) -> Result<(), Self::Error> {
self.inner
.write_read(address, bytes, buffer)
.map_err(ForwardError)
}
fn transaction(
&mut self,
address: SevenBitAddress,
operations: &mut [eh1_0::i2c::Operation],
) -> Result<(), Self::Error> {
let ops = operations.iter_mut().map(|op| match op {
eh1_0::i2c::Operation::Read(ref mut buff) => {
eh0_2::blocking::i2c::Operation::Read(buff)
}
eh1_0::i2c::Operation::Write(buff) => eh0_2::blocking::i2c::Operation::Write(buff),
});
self.inner.exec_iter(address, ops).map_err(ForwardError)
}
}
}
#[cfg(feature = "embedded-io")]
#[cfg_attr(docsrs, doc(cfg(feature = "embedded-io")))]
mod serial {
use super::{Forward, ForwardError};
impl<E: core::fmt::Debug> embedded_io::Error for ForwardError<E> {
fn kind(&self) -> embedded_io::ErrorKind {
embedded_io::ErrorKind::Other
}
}
impl<T, E> embedded_io::ErrorType for Forward<T>
where
T: eh0_2::blocking::serial::Write<u8, Error = E>,
E: core::fmt::Debug,
{
type Error = ForwardError<E>;
}
impl<T, E> embedded_io::Write for Forward<T>
where
T: eh0_2::blocking::serial::Write<u8, Error = E>,
E: core::fmt::Debug,
{
fn write(&mut self, words: &[u8]) -> Result<usize, Self::Error> {
self.inner
.bwrite_all(words)
.map_err(ForwardError)
.and(Ok(words.len()))
}
fn flush(&mut self) -> Result<(), Self::Error> {
self.inner.bflush().map_err(ForwardError)
}
}
}