chromiumoxide/handler/
target_message_future.rs1use 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>;
18
19pin_project! {
20 pub struct TargetMessageFuture<T> {
21 #[pin]
22 rx_request: oneshot::Receiver<T>,
23 #[pin]
24 target_sender: mpsc::Sender<TargetMessage>,
25 message: Option<TargetMessage>,
26 }
27}
28
29impl<T> TargetMessageFuture<T> {
30 pub fn new(
31 target_sender: TargetSender,
32 message: TargetMessage,
33 rx_request: oneshot::Receiver<T>,
34 ) -> Self {
35 Self {
36 target_sender,
37 rx_request,
38 message: Some(message),
39 }
40 }
41
42 pub(crate) fn wait(
49 target_sender: TargetSender,
50 make_msg: impl FnOnce(oneshot::Sender<ArcHttpRequest>) -> TargetMessage,
51 ) -> TargetMessageFuture<ArcHttpRequest> {
52 let (tx, rx_request) = oneshot_channel();
53 let message = make_msg(tx);
54 TargetMessageFuture::new(target_sender, message, rx_request)
55 }
56
57 pub fn wait_for_navigation(target_sender: TargetSender) -> TargetMessageFuture<ArcHttpRequest> {
62 Self::wait(target_sender, TargetMessage::WaitForNavigation)
63 }
64
65 pub fn wait_for_network_idle(
71 target_sender: TargetSender,
72 ) -> TargetMessageFuture<ArcHttpRequest> {
73 Self::wait(target_sender, TargetMessage::WaitForNetworkIdle)
74 }
75
76 pub fn wait_for_network_almost_idle(
81 target_sender: TargetSender,
82 ) -> TargetMessageFuture<ArcHttpRequest> {
83 Self::wait(target_sender, TargetMessage::WaitForNetworkAlmostIdle)
84 }
85}
86
87impl<T> Future for TargetMessageFuture<T> {
88 type Output = Result<T>;
89
90 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
91 let mut this = self.project();
92
93 if this.message.is_some() {
94 match this.target_sender.poll_ready(cx) {
95 Poll::Ready(Err(e)) => Poll::Ready(Err(e.into())),
96 Poll::Ready(Ok(_)) => {
97 let message = this.message.take().expect("existence checked above");
98 this.target_sender.start_send(message)?;
99 cx.waker().wake_by_ref();
100 Poll::Pending
101 }
102 Poll::Pending => Poll::Pending,
103 }
104 } else {
105 this.rx_request.as_mut().poll(cx).map_err(Into::into)
106 }
107 }
108}