penumbra_sdk_proto/state/
future.rs

1use std::{
2    future::Future,
3    pin::Pin,
4    task::{Context, Poll},
5};
6
7use anyhow::{Context as _, Result};
8use pin_project::pin_project;
9use prost::Message;
10
11use crate::DomainType;
12
13/// A future that resolves to a protobuf message.
14#[pin_project]
15pub struct ProtoFuture<P, F> {
16    #[pin]
17    pub(super) inner: F,
18    pub(super) _marker: std::marker::PhantomData<P>,
19}
20
21/// A future that resolves to a domain type.
22#[pin_project]
23pub struct DomainFuture<D, F> {
24    #[pin]
25    pub(super) inner: F,
26    pub(super) _marker: std::marker::PhantomData<D>,
27}
28
29impl<F, P> Future for ProtoFuture<P, F>
30where
31    F: Future<Output = Result<Option<Vec<u8>>>>,
32    P: Message + Default,
33{
34    type Output = Result<Option<P>>;
35    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
36        let this = self.project();
37        match this.inner.poll(cx) {
38            Poll::Ready(Ok(Some(bytes))) => {
39                let v = P::decode(&*bytes).context("could not decode proto from bytes")?;
40                Poll::Ready(Ok(Some(v)))
41            }
42            Poll::Ready(Ok(None)) => Poll::Ready(Ok(None)),
43            Poll::Ready(Err(e)) => Poll::Ready(Err(e)),
44            Poll::Pending => Poll::Pending,
45        }
46    }
47}
48
49impl<D, F> Future for DomainFuture<D, F>
50where
51    F: Future<Output = Result<Option<Vec<u8>>>>,
52    D: DomainType,
53    anyhow::Error: From<<D as TryFrom<D::Proto>>::Error>,
54{
55    type Output = Result<Option<D>>;
56    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
57        let this = self.project();
58        match this.inner.poll(cx) {
59            Poll::Ready(Ok(Some(bytes))) => {
60                let v = D::Proto::decode(&*bytes).context("could not decode proto from bytes")?;
61                let v = D::try_from(v)
62                    .map_err(anyhow::Error::from)
63                    .context("could not parse domain type from proto")?;
64                Poll::Ready(Ok(Some(v)))
65            }
66            Poll::Ready(Ok(None)) => Poll::Ready(Ok(None)),
67            Poll::Ready(Err(e)) => Poll::Ready(Err(e)),
68            Poll::Pending => Poll::Pending,
69        }
70    }
71}