Skip to main content

gstreamer/
promise_futures.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use std::{
4    ops::Deref,
5    pin::Pin,
6    task::{Context, Poll},
7};
8
9use crate::promise::{Promise, PromiseError};
10use crate::{PromiseResult, StructureRef};
11
12#[derive(Debug)]
13pub struct PromiseFuture(
14    pub(crate) Promise,
15    pub(crate) futures_channel::oneshot::Receiver<()>,
16);
17
18pub struct PromiseReply(Promise);
19
20impl std::future::Future for PromiseFuture {
21    type Output = Result<Option<PromiseReply>, PromiseError>;
22
23    fn poll(mut self: Pin<&mut Self>, context: &mut Context) -> Poll<Self::Output> {
24        match Pin::new(&mut self.1).poll(context) {
25            Poll::Ready(Err(_)) => panic!("Sender dropped before callback was called"),
26            Poll::Ready(Ok(())) => {
27                let res = match self.0.wait() {
28                    PromiseResult::Replied => {
29                        if self.0.get_reply().is_none() {
30                            Ok(None)
31                        } else {
32                            Ok(Some(PromiseReply(self.0.clone())))
33                        }
34                    }
35                    PromiseResult::Interrupted => Err(PromiseError::Interrupted),
36                    PromiseResult::Expired => Err(PromiseError::Expired),
37                    PromiseResult::Pending => {
38                        panic!("Promise resolved but returned Pending");
39                    }
40                    err => Err(PromiseError::Other(err)),
41                };
42                Poll::Ready(res)
43            }
44            Poll::Pending => Poll::Pending,
45        }
46    }
47}
48
49impl futures_core::future::FusedFuture for PromiseFuture {
50    fn is_terminated(&self) -> bool {
51        self.1.is_terminated()
52    }
53}
54
55impl Deref for PromiseReply {
56    type Target = StructureRef;
57
58    #[inline]
59    fn deref(&self) -> &StructureRef {
60        self.0.get_reply().expect("Promise without reply")
61    }
62}
63
64impl std::fmt::Debug for PromiseReply {
65    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
66        let mut debug = f.debug_tuple("PromiseReply");
67
68        match self.0.get_reply() {
69            Some(reply) => debug.field(reply),
70            None => debug.field(&"<no reply>"),
71        }
72        .finish()
73    }
74}