Skip to main content

tempo_commonware_node/
utils.rs

1use std::{
2    future::Future,
3    ops::{Deref, DerefMut},
4    pin::Pin,
5    task::Poll,
6};
7
8use alloy_primitives::B256;
9use commonware_cryptography::ed25519::PublicKey;
10use futures::future::FusedFuture;
11use pin_project::pin_project;
12
13pub(crate) fn public_key_to_b256(key: &PublicKey) -> B256 {
14    key.as_ref()
15        .try_into()
16        .expect("ed25519 pub keys always map to B256")
17}
18
19/// A vendored version of [`commonware_utils::futures::OptionFuture`] to implement
20/// [`futures::future::FusedFuture`].
21///
22/// An optional future that yields [Poll::Pending] when [None]. Useful within `select!` macros,
23/// where a future may be conditionally present.
24///
25/// Not to be confused with [futures::future::OptionFuture], which resolves to [None] immediately
26/// when the inner future is `None`.
27#[pin_project]
28pub(crate) struct OptionFuture<F>(#[pin] Option<F>);
29
30impl<F: Future> Default for OptionFuture<F> {
31    fn default() -> Self {
32        Self(None)
33    }
34}
35
36impl<F: Future> From<Option<F>> for OptionFuture<F> {
37    fn from(opt: Option<F>) -> Self {
38        Self(opt)
39    }
40}
41
42impl<F: Future> Deref for OptionFuture<F> {
43    type Target = Option<F>;
44
45    fn deref(&self) -> &Self::Target {
46        &self.0
47    }
48}
49
50impl<F: Future> DerefMut for OptionFuture<F> {
51    fn deref_mut(&mut self) -> &mut Self::Target {
52        &mut self.0
53    }
54}
55
56impl<F: Future> Future for OptionFuture<F> {
57    type Output = F::Output;
58
59    fn poll(self: Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> Poll<Self::Output> {
60        let this = self.project();
61        match this.0.as_pin_mut() {
62            Some(fut) => fut.poll(cx),
63            None => Poll::Pending,
64        }
65    }
66}
67
68impl<F: Future> FusedFuture for OptionFuture<F> {
69    fn is_terminated(&self) -> bool {
70        self.0.is_none()
71    }
72}
73
74#[cfg(test)]
75mod tests {
76    use std::task::Poll;
77
78    use futures::{channel::oneshot, executor::block_on, pin_mut};
79
80    use crate::utils::OptionFuture;
81
82    #[test]
83    fn option_future() {
84        block_on(async {
85            let option_future = OptionFuture::<oneshot::Receiver<()>>::from(None);
86            pin_mut!(option_future);
87
88            let waker = futures::task::noop_waker();
89            let mut cx = std::task::Context::from_waker(&waker);
90            assert!(option_future.poll(&mut cx).is_pending());
91
92            let (tx, rx) = oneshot::channel();
93            let option_future: OptionFuture<_> = Some(rx).into();
94            pin_mut!(option_future);
95
96            tx.send(1usize).unwrap();
97            assert_eq!(option_future.poll(&mut cx), Poll::Ready(Ok(1)));
98        });
99    }
100}