dyn_phy 0.1.0-alpha3

object-safe version of smoltcp::phy traits
Documentation
use smoltcp::phy::{
    RxToken,
    TxToken,
};

tiny_fn::tiny_fn! {
    struct ByteWrap = FnOnce(b: &mut [u8]);

    struct DynRxInner = FnOnce(f: ByteWrap);
    struct DynTxInner = FnOnce(len: usize, f: ByteWrap);
}

/// Object-safe version of [`TxToken`].
pub struct DynRxToken<'a>(DynRxInner<'a>);

/// Object-safe version of [`RxToken`].
pub struct DynTxToken<'a>(DynTxInner<'a>);

impl<'a> DynRxToken<'a> {
    #[inline]
    pub fn new(rx: impl RxToken + 'a) -> Self {
        Self(DynRxInner::new(move |f| {
            rx.consume(move |b| {
                f.call(b);
            });
        }))
    }
}

impl RxToken for DynRxToken<'_> {
    #[inline]
    fn consume<R, F>(self, f: F) -> R
    where
        F: FnOnce(&mut [u8]) -> R,
    {
        let mut result = None;

        {
            let result = &mut result;

            let wrapped = ByteWrap::new(move |b| {
                *result = Some(f(b));
            });

            self.0.call(wrapped);
        }

        result.unwrap()
    }
}

impl<'a> DynTxToken<'a> {
    #[inline]
    pub fn new(t: impl TxToken + 'a) -> Self {
        Self(DynTxInner::new(move |len, f| {
            t.consume(len, move |b| {
                f.call(b);
            })
        }))
    }

    #[inline]
    pub fn send(self, buf: &[u8]) {
        self.consume(buf.len(), |inner| inner.copy_from_slice(buf))
    }
}

impl TxToken for DynTxToken<'_> {
    #[inline]
    fn consume<R, F>(self, len: usize, f: F) -> R
    where
        F: FnOnce(&mut [u8]) -> R,
    {
        let mut result = None;

        {
            let result = &mut result;

            self.0.call(
                len,
                ByteWrap::new(move |b| {
                    *result = Some(f(b));
                }),
            );
        }

        result.unwrap()
    }
}