dyn_phy 0.1.0-alpha3

object-safe version of smoltcp::phy traits
Documentation
#![doc = include_str!("../README.md")]
#![no_std]

use smoltcp::{
    phy,
    phy::DeviceCapabilities,
    time::Instant,
};

mod ext;
mod token;

pub use ext::DynPhyExt;
pub use token::*;

/// Object-safe version of [`phy::Device`].
pub trait DynPhy {
    /// Construct a token pair consisting of one receive token and one transmit token.
    ///
    /// The additional transmit token makes it possible to generate a reply packet based
    /// on the contents of the received packet. For example, this makes it possible to
    /// handle arbitrarily large ICMP echo ("ping") requests, where the all received bytes
    /// need to be sent back, without heap allocation.
    ///
    /// The timestamp must be a number of milliseconds, monotonically increasing since an
    /// arbitrary moment in time, such as system startup.
    fn dyn_receive(&mut self, timestamp: Instant) -> Option<(DynRxToken<'_>, DynTxToken<'_>)>;

    /// Construct a transmit token.
    ///
    /// The timestamp must be a number of milliseconds, monotonically increasing since an
    /// arbitrary moment in time, such as system startup.
    fn dyn_transmit(&mut self, timestamp: Instant) -> Option<DynTxToken<'_>>;

    /// Get a description of device capabilities.
    fn capabilities(&self) -> DeviceCapabilities;
}

impl<D> DynPhy for D
where
    D: phy::Device,
{
    #[inline]
    fn dyn_receive(&mut self, timestamp: Instant) -> Option<(DynRxToken, DynTxToken)> {
        let (rx, tx) = self.receive(timestamp)?;

        let dyn_rx = DynRxToken::new(rx);
        let dyn_tx = DynTxToken::new(tx);

        Some((dyn_rx, dyn_tx))
    }

    #[inline]
    fn dyn_transmit(&mut self, timestamp: Instant) -> Option<DynTxToken> {
        let tx = self.transmit(timestamp)?;

        Some(DynTxToken::new(tx))
    }

    #[inline]
    fn capabilities(&self) -> DeviceCapabilities {
        self.capabilities()
    }
}