1use alloc::collections::VecDeque;
2use alloc::vec;
3use alloc::vec::Vec;
4
5use crate::phy::{self, ChecksumCapabilities, Device, DeviceCapabilities, Medium};
6use crate::time::Instant;
7
8#[derive(Debug)]
10pub struct Loopback {
11 pub(crate) queue: VecDeque<Vec<u8>>,
12 medium: Medium,
13}
14
15#[allow(clippy::new_without_default)]
16impl Loopback {
17 pub fn new(medium: Medium) -> Loopback {
22 Loopback {
23 queue: VecDeque::new(),
24 medium,
25 }
26 }
27}
28
29impl Device for Loopback {
30 type RxToken<'a> = RxToken;
31 type TxToken<'a> = TxToken<'a>;
32
33 fn capabilities(&self) -> DeviceCapabilities {
34 DeviceCapabilities {
35 max_transmission_unit: 65535,
36 medium: self.medium,
37 checksum: ChecksumCapabilities::ignored(),
38 ..DeviceCapabilities::default()
39 }
40 }
41
42 fn receive(&mut self, _timestamp: Instant) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> {
43 self.queue.pop_front().map(move |buffer| {
44 let rx = RxToken { buffer };
45 let tx = TxToken {
46 queue: &mut self.queue,
47 };
48 (rx, tx)
49 })
50 }
51
52 fn transmit(&mut self, _timestamp: Instant) -> Option<Self::TxToken<'_>> {
53 Some(TxToken {
54 queue: &mut self.queue,
55 })
56 }
57}
58
59#[doc(hidden)]
60pub struct RxToken {
61 buffer: Vec<u8>,
62}
63
64impl phy::RxToken for RxToken {
65 fn consume<R, F>(self, f: F) -> R
66 where
67 F: FnOnce(&[u8]) -> R,
68 {
69 f(&self.buffer)
70 }
71}
72
73#[doc(hidden)]
74#[derive(Debug)]
75pub struct TxToken<'a> {
76 queue: &'a mut VecDeque<Vec<u8>>,
77}
78
79impl<'a> phy::TxToken for TxToken<'a> {
80 fn consume<R, F>(self, len: usize, f: F) -> R
81 where
82 F: FnOnce(&mut [u8]) -> R,
83 {
84 let mut buffer = vec![0; len];
85 let result = f(&mut buffer);
86 self.queue.push_back(buffer);
87 result
88 }
89}