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>;
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 message: Option<TargetMessage>,
22 }
23}
24
25impl<T> TargetMessageFuture<T> {
26 pub fn new(
27 target_sender: TargetSender,
28 message: TargetMessage,
29 rx_request: oneshot::Receiver<T>,
30 ) -> Self {
31 Self {
32 target_sender,
33 rx_request,
34 message: Some(message),
35 }
36 }
37
38 pub fn wait_for_navigation(target_sender: TargetSender) -> TargetMessageFuture<ArcHttpRequest> {
39 let (tx, rx_request) = oneshot_channel();
40
41 let message = TargetMessage::WaitForNavigation(tx);
42
43 TargetMessageFuture::new(target_sender, message, rx_request)
44 }
45}
46
47impl<T> Future for TargetMessageFuture<T> {
48 type Output = Result<T>;
49
50 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
51 let mut this = self.project();
52
53 if this.message.is_some() {
54 match this.target_sender.poll_ready(cx) {
55 Poll::Ready(Err(e)) => Poll::Ready(Err(e.into())),
56 Poll::Ready(Ok(_)) => {
57 let message = this.message.take().expect("existence checked above");
58 this.target_sender.start_send(message)?;
59
60 cx.waker().wake_by_ref();
61 Poll::Pending
62 }
63 Poll::Pending => Poll::Pending,
64 }
65 } else {
66 this.rx_request.as_mut().poll(cx).map_err(Into::into)
67 }
68 }
69}