use super::socket::UdpSocket; use std::io; use std::net::SocketAddr; use futures::{Async, Future, Poll}; /// A future used to receive a datagram from a UDP socket. /// /// This is created by the `UdpSocket::recv_dgram` method. #[must_use = "futures do nothing unless polled"] #[derive(Debug)] pub struct RecvDgram { /// None means future was completed state: Option>, } /// A struct is used to represent the full info of RecvDgram. #[derive(Debug)] struct RecvDgramInner { /// Rx socket socket: UdpSocket, /// The received data will be put in the buffer buffer: T, } /// Components of a `RecvDgram` future, returned from `into_parts`. #[derive(Debug)] pub struct Parts { /// The socket pub socket: UdpSocket, /// The buffer pub buffer: T, _priv: (), } impl RecvDgram { /// Create a new future to receive UDP Datagram pub(crate) fn new(socket: UdpSocket, buffer: T) -> RecvDgram { let inner = RecvDgramInner { socket: socket, buffer: buffer, }; RecvDgram { state: Some(inner) } } /// Consume the `RecvDgram`, returning the socket and buffer. /// /// ``` /// # extern crate tokio_udp; /// /// use tokio_udp::UdpSocket; /// /// # pub fn main() { /// /// let socket = UdpSocket::bind(&([127, 0, 0, 1], 0).into()).unwrap(); /// let mut buffer = vec![0; 4096]; /// /// let future = socket.recv_dgram(buffer); /// /// // ... polling `future` ... giving up (e.g. after timeout) /// /// let parts = future.into_parts(); /// /// let socket = parts.socket; // extract the socket /// let buffer = parts.buffer; // extract the buffer /// /// # } /// ``` /// # Panics /// /// If called after the future has completed. pub fn into_parts(mut self) -> Parts { let state = self .state .take() .expect("into_parts called after completion"); Parts { socket: state.socket, buffer: state.buffer, _priv: (), } } } impl Future for RecvDgram where T: AsMut<[u8]>, { type Item = (UdpSocket, T, usize, SocketAddr); type Error = io::Error; fn poll(&mut self) -> Poll { let (n, addr) = { let ref mut inner = self .state .as_mut() .expect("RecvDgram polled after completion"); try_ready!(inner.socket.poll_recv_from(inner.buffer.as_mut())) }; let inner = self.state.take().unwrap(); Ok(Async::Ready((inner.socket, inner.buffer, n, addr))) } }