chromiumoxide/handler/
httpfuture.rs

1use futures::channel::mpsc;
2use futures::future::{Fuse, FusedFuture};
3use futures::FutureExt;
4use pin_project_lite::pin_project;
5use std::future::Future;
6use std::pin::Pin;
7use std::task::{Context, Poll};
8
9use crate::handler::commandfuture::CommandFuture;
10use crate::handler::target::TargetMessage;
11use crate::handler::target_message_future::TargetMessageFuture;
12use crate::{ArcHttpRequest, Result};
13use chromiumoxide_types::Command;
14
15type ArcRequest = ArcHttpRequest;
16
17pin_project! {
18    pub struct HttpFuture<T: Command> {
19        #[pin]
20        command: Fuse<CommandFuture<T>>,
21        #[pin]
22        navigation: TargetMessageFuture<ArcHttpRequest>,
23    }
24}
25
26impl<T: Command> HttpFuture<T> {
27    pub fn new(sender: mpsc::Sender<TargetMessage>, command: CommandFuture<T>) -> Self {
28        Self {
29            command: command.fuse(),
30            navigation: TargetMessageFuture::<T>::wait_for_navigation(sender),
31        }
32    }
33}
34
35impl<T> Future for HttpFuture<T>
36where
37    T: Command,
38{
39    type Output = Result<ArcRequest>;
40
41    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
42        let this = self.project();
43
44        // 1. First complete command request future
45        // 2. Switch polls navigation
46        if this.command.is_terminated() {
47            this.navigation.poll(cx)
48        } else {
49            match this.command.poll(cx) {
50                Poll::Ready(Ok(_command_response)) => {
51                    cx.waker().wake_by_ref();
52                    Poll::Pending
53                }
54                Poll::Ready(Err(e)) => Poll::Ready(Err(e)),
55                Poll::Pending => Poll::Pending,
56            }
57        }
58    }
59}