use crate::Result; use crate::wire::pretty_print::{PrettyPrint, PrettyPrinter}; use crate::phy::{self, DeviceCapabilities, Device}; use crate::time::Instant; /// A tracer device. /// /// A tracer is a device that pretty prints all packets traversing it /// using the provided writer function, and then passes them to another /// device. pub struct Tracer Device<'a>, P: PrettyPrint> { inner: D, writer: fn(Instant, PrettyPrinter

), } impl Device<'a>, P: PrettyPrint> Tracer { /// Create a tracer device. pub fn new(inner: D, writer: fn(timestamp: Instant, printer: PrettyPrinter

)) -> Tracer { Tracer { inner, writer } } /// Get a reference to the underlying device. /// /// Even if the device offers reading through a standard reference, it is inadvisable to /// directly read from the device as doing so will circumvent the tracing. pub fn get_ref(&self) -> &D { &self.inner } /// Get a mutable reference to the underlying device. /// /// It is inadvisable to directly read from the device as doing so will circumvent the tracing. pub fn get_mut(&mut self) -> &mut D { &mut self.inner } /// Return the underlying device, consuming the tracer. pub fn into_inner(self) -> D { self.inner } } impl<'a, D, P> Device<'a> for Tracer where D: for<'b> Device<'b>, P: PrettyPrint + 'a, { type RxToken = RxToken<>::RxToken, P>; type TxToken = TxToken<>::TxToken, P>; fn capabilities(&self) -> DeviceCapabilities { self.inner.capabilities() } fn receive(&'a mut self) -> Option<(Self::RxToken, Self::TxToken)> { let &mut Self { ref mut inner, writer, .. } = self; inner.receive().map(|(rx_token, tx_token)| { let rx = RxToken { token: rx_token, writer: writer }; let tx = TxToken { token: tx_token, writer: writer }; (rx, tx) }) } fn transmit(&'a mut self) -> Option { let &mut Self { ref mut inner, writer } = self; inner.transmit().map(|tx_token| { TxToken { token: tx_token, writer: writer } }) } } #[doc(hidden)] pub struct RxToken { token: Rx, writer: fn(Instant, PrettyPrinter

) } impl phy::RxToken for RxToken { fn consume(self, timestamp: Instant, f: F) -> Result where F: FnOnce(&mut [u8]) -> Result { let Self { token, writer } = self; token.consume(timestamp, |buffer| { writer(timestamp, PrettyPrinter::

::new("<- ", &buffer)); f(buffer) }) } } #[doc(hidden)] pub struct TxToken { token: Tx, writer: fn(Instant, PrettyPrinter

) } impl phy::TxToken for TxToken { fn consume(self, timestamp: Instant, len: usize, f: F) -> Result where F: FnOnce(&mut [u8]) -> Result { let Self { token, writer } = self; token.consume(timestamp, len, |buffer| { let result = f(buffer); writer(timestamp, PrettyPrinter::

::new("-> ", &buffer)); result }) } }