use alloc::collections::VecDeque; use alloc::vec; use alloc::vec::Vec; use crate::phy::{self, ChecksumCapabilities, Device, DeviceCapabilities, Medium}; use crate::time::Instant; /// A loopback device. #[derive(Debug)] pub struct Loopback { pub(crate) queue: VecDeque>, medium: Medium, } #[allow(clippy::new_without_default)] impl Loopback { /// Creates a loopback device. /// /// Every packet transmitted through this device will be received through it /// in FIFO order. pub fn new(medium: Medium) -> Loopback { Loopback { queue: VecDeque::new(), medium, } } } impl Device for Loopback { type RxToken<'a> = RxToken; type TxToken<'a> = TxToken<'a>; fn capabilities(&self) -> DeviceCapabilities { DeviceCapabilities { max_transmission_unit: 65535, medium: self.medium, checksum: ChecksumCapabilities::ignored(), ..DeviceCapabilities::default() } } fn receive(&mut self, _timestamp: Instant) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> { self.queue.pop_front().map(move |buffer| { let rx = RxToken { buffer }; let tx = TxToken { queue: &mut self.queue, }; (rx, tx) }) } fn transmit(&mut self, _timestamp: Instant) -> Option> { Some(TxToken { queue: &mut self.queue, }) } } #[doc(hidden)] pub struct RxToken { buffer: Vec, } impl phy::RxToken for RxToken { fn consume(self, f: F) -> R where F: FnOnce(&[u8]) -> R, { f(&self.buffer) } } #[doc(hidden)] #[derive(Debug)] pub struct TxToken<'a> { queue: &'a mut VecDeque>, } impl<'a> phy::TxToken for TxToken<'a> { fn consume(self, len: usize, f: F) -> R where F: FnOnce(&mut [u8]) -> R, { let mut buffer = vec![0; len]; let result = f(&mut buffer); self.queue.push_back(buffer); result } }