Skip to main content

chaser_oxide/handler/
target_message_future.rs

1use futures::channel::{
2    mpsc,
3    oneshot::{self, channel as oneshot_channel},
4};
5use pin_project_lite::pin_project;
6use std::future::Future;
7use std::pin::Pin;
8use std::task::{Context, Poll};
9
10use crate::handler::target::TargetMessage;
11use crate::{error::Result, ArcHttpRequest};
12
13type TargetSender = mpsc::Sender<TargetMessage>;
14
15pin_project! {
16    pub struct TargetMessageFuture<T> {
17        #[pin]
18        rx_request: oneshot::Receiver<T>,
19        #[pin]
20        target_sender: mpsc::Sender<TargetMessage>,
21
22        message: Option<TargetMessage>,
23    }
24}
25
26impl<T> TargetMessageFuture<T> {
27    pub fn new(
28        target_sender: TargetSender,
29        message: TargetMessage,
30        rx_request: oneshot::Receiver<T>,
31    ) -> Self {
32        Self {
33            target_sender,
34            rx_request,
35            message: Some(message),
36        }
37    }
38
39    pub fn wait_for_navigation(target_sender: TargetSender) -> TargetMessageFuture<ArcHttpRequest> {
40        let (tx, rx_request) = oneshot_channel();
41
42        let message = TargetMessage::WaitForNavigation(tx);
43
44        TargetMessageFuture::new(target_sender, message, rx_request)
45    }
46}
47
48impl<T> Future for TargetMessageFuture<T> {
49    type Output = Result<T>;
50
51    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
52        let mut this = self.project();
53
54        if this.message.is_some() {
55            match this.target_sender.poll_ready(cx) {
56                Poll::Ready(Err(e)) => Poll::Ready(Err(e.into())),
57                Poll::Ready(Ok(_)) => {
58                    let message = this.message.take().expect("existence checked above");
59                    this.target_sender.start_send(message)?;
60
61                    cx.waker().wake_by_ref();
62                    Poll::Pending
63                }
64                Poll::Pending => Poll::Pending,
65            }
66        } else {
67            this.rx_request.as_mut().poll(cx).map_err(Into::into)
68        }
69    }
70}