use std::cell::Cell;
use std::future::Future;
use std::pin::Pin;
use std::ptr::NonNull;
use std::task::{Context, Poll};
use crate::side_channel::SideChannelFuture;
pub(crate) struct Sender<T, Fut> {
future: Fut,
result: Cell<Option<T>>,
}
impl<T, Fut> Sender<T, Fut> {
pub unsafe fn new(future: Fut) -> Self {
let result = Cell::new(None);
Self { future, result }
}
}
impl<T, Fut> Future for Sender<T, Fut>
where
Fut: Future<Output = T>,
{
type Output = ();
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let future = unsafe { self.as_mut().map_unchecked_mut(|this| &mut this.future) };
match future.poll(cx) {
Poll::Pending => Poll::Pending,
Poll::Ready(value) => {
self.result.set(Some(value));
Poll::Ready(())
}
}
}
}
impl<T, Fut> SideChannelFuture for Sender<T, Fut>
where
Fut: Future<Output = T>,
{
unsafe fn get_result_pointer(&self) -> NonNull<Cell<Option<()>>> {
let result = &self.result;
let ptr: NonNull<Cell<Option<T>>> =
unsafe { NonNull::new_unchecked(result as *const _ as *mut _) };
let ptr: NonNull<Cell<Option<()>>> = unsafe { std::mem::transmute(ptr) };
ptr
}
}