use futures::{Sink, Stream}; use smoltcp::phy::DeviceCapabilities; use std::{ io, pin::Pin, task::{Context, Poll}, }; use tokio::sync::mpsc::{channel, Receiver, Sender}; use tokio_util::sync::{PollSendError, PollSender}; use super::device::AsyncDevice; /// A device that send and receive packets using a channel. pub struct ChannelDevice { recv: Receiver>>, send: PollSender>, caps: DeviceCapabilities, } impl ChannelDevice { /// Make a new `ChannelDevice` with the given `recv` and `send` channels. /// /// The `caps` is used to determine the device capabilities. `DeviceCapabilities::max_transmission_unit` must be set. pub fn new(caps: DeviceCapabilities) -> (Self, Sender>>, Receiver>) { let (tx1, rx1) = channel(1000); let (tx2, rx2) = channel(1000); ( ChannelDevice { send: PollSender::new(tx1), recv: rx2, caps, }, tx2, rx1, ) } } impl Stream for ChannelDevice { type Item = io::Result>; fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { self.recv.poll_recv(cx) } } fn map_err(e: PollSendError>) -> io::Error { io::Error::new(io::ErrorKind::Other, e) } impl Sink> for ChannelDevice { type Error = io::Error; fn poll_ready(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { self.send.poll_reserve(cx).map_err(map_err) } fn start_send(mut self: Pin<&mut Self>, item: Vec) -> Result<(), Self::Error> { self.send.send_item(item).map_err(map_err) } fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { self.send.poll_reserve(cx).map_err(map_err) } fn poll_close(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll> { Poll::Ready(Ok(())) } } impl AsyncDevice for ChannelDevice { fn capabilities(&self) -> &DeviceCapabilities { &self.caps } }