use std::future::Future;
use std::pin::Pin;
use std::task::{Context, Poll};
use tokio::sync::oneshot;
use tokio::sync::oneshot::Receiver;
pub struct Item<T> {
receiver: oneshot::Receiver<T>
}
impl<T> Item<T> {
#[allow(dead_code)]
pub fn new(receiver: oneshot::Receiver<T>) -> Self {
Self {
receiver,
}
}
}
impl<T> AsRef<oneshot::Receiver<T>> for Item<T> {
fn as_ref(&self) -> &Receiver<T> {
&self.receiver
}
}
impl<T> Future for Item<T> {
type Output = Result<T, oneshot::error::RecvError>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
Pin::new(&mut self.get_mut().receiver).poll(cx)
}
}
#[cfg(test)]
mod tests {
use super::*;
use tokio::test;
use tokio::sync::oneshot;
#[test]
async fn test_item_successful_receive() {
let (tx, rx) = oneshot::channel();
let item = Item::new(rx);
tx.send(42).unwrap();
let result = item.await;
assert!(result.is_ok());
assert_eq!(result.unwrap(), 42);
}
#[tokio::test]
async fn test_item_sender_dropped() {
let (tx, rx) = oneshot::channel::<i32>();
let item = Item::new(rx);
drop(tx);
let result = item.await;
assert!(result.is_err());
}
#[test]
async fn test_as_ref() {
let (tx, rx) = oneshot::channel::<i32>();
let item = Item::new(rx);
let _receiver_ref: &oneshot::Receiver<i32> = item.as_ref();
drop(tx);
}
#[test]
async fn test_future_behavior() {
let (tx, rx) = oneshot::channel();
let item = Item::new(rx);
let send_task = tokio::spawn(async move {
tokio::time::sleep(tokio::time::Duration::from_millis(50)).await;
tx.send("hello").unwrap();
});
let result = item.await.unwrap();
assert_eq!(result, "hello");
send_task.await.unwrap();
}
}