dyn_phy 0.1.0-alpha3

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

use crate::DynPhy;

mod private {
    pub trait Sealed {}
}

impl<T> private::Sealed for T where T: DynPhy {}

/// Convenience methods for [`DynPhy`].
pub trait DynPhyExt: DynPhy + private::Sealed {
    /// Attempt to send a frame. Returns true iff the frame was sent.
    #[inline]
    fn send(&mut self, timestamp: Instant, data: &[u8]) -> bool {
        let Some(tx) = self.dyn_transmit(timestamp) else {
            return false;
        };

        tx.send(data);

        true
    }

    /// Attempt to send a frame. Returns true iff the frame was sent.
    ///
    /// Convenience over [`Self::send`] passing [`Instant::now`] for the timestamp.
    #[cfg(feature = "std")]
    #[inline]
    fn send_now(&mut self, data: &[u8]) -> bool {
        self.send(Instant::now(), data)
    }

    /// Receive an incoming frame and optionally respond using the provided transmit closure.
    ///
    /// The function parameter is a [`FnMut`] for object-safety but is intended to be called at most
    /// once with a response buffer. Only the first invocation will send a response; subsequent
    /// invocations will be ignored.
    #[inline]
    fn receive(
        &mut self,
        timestamp: Instant,
        f: impl FnOnce(&mut [u8], &mut dyn FnMut(&[u8])),
    ) -> bool {
        let Some((rx, tx)) = self.dyn_receive(timestamp) else {
            return false;
        };

        let mut tx = Some(tx);
        let tx = &mut tx;

        rx.consume(move |b| {
            f(b, &mut |data| {
                if let Some(tx) = tx.take() {
                    tx.consume(data.len(), move |dat| {
                        dat.copy_from_slice(data);
                    });
                }
            });
        });

        true
    }

    /// Receive an incoming frame and optionally respond using the provided transmit closure.
    /// Convenience over [`Self::receive`] passing [`Instant::now`].
    ///
    /// The function parameter is a [`FnMut`] for object-safety but is intended to be called at most
    /// once with a response buffer. Only the first invocation will send a response; subsequent
    /// invocations will be ignored.
    #[cfg(feature = "std")]
    #[inline]
    fn receive_now(&mut self, f: impl FnOnce(&mut [u8], &mut dyn FnMut(&[u8]))) -> bool {
        self.receive(Instant::now(), f)
    }
}

impl<T> DynPhyExt for T where T: DynPhy {}