fidl_next_bind/future/
send.rs1use core::future::Future;
6use core::pin::Pin;
7use core::task::{Context, Poll, ready};
8
9use fidl_next_codec::EncodeError;
10use fidl_next_protocol::{NonBlockingTransport, Transport};
11use pin_project::pin_project;
12
13use crate::Error;
14
15macro_rules! define_send_future {
16 (
17 $(#[$metas:meta])*
18 $name:ident<$($lifetime:lifetime,)? T: Transport>($future:ty) => $encoded:ident {
19 state = $state:ident,
20 proj = $proj:ident,
21 own = $own:ident,
22 }
23 ) => {
24 #[pin_project(project = $proj, project_replace = $own)]
25 enum $state<$($lifetime,)? T: Transport> {
26 EncodeError(EncodeError),
27 Sending(#[pin] $future),
28 Finished,
29 }
30
31 impl<$($lifetime,)? T: Transport> $state<$($lifetime,)? T> {
32 fn poll_state(
33 mut self: Pin<&mut Self>,
34 cx: &mut Context<'_>,
35 ) -> Poll<Result<(), Error<T::Error>>> {
36 match self.as_mut().project() {
37 $proj::EncodeError(_) => {
38 let state = self.project_replace(Self::Finished);
39 let $own::EncodeError(error) = state else {
40 unreachable!();
41 };
42 Poll::Ready(Err(Error::Encode(error)))
43 }
44 $proj::Sending(future) => match ready!(future.poll(cx)) {
45 Ok(()) => Poll::Ready(Ok(())),
46 Err(error) => Poll::Ready(Err(Error::Protocol(error))),
47 },
48 $proj::Finished => panic!("State polled after completing"),
49 }
50 }
51
52 fn send_immediately(self) -> Result<(), Error<T::Error>>
53 where
54 T: NonBlockingTransport,
55 {
56 match self {
57 Self::EncodeError(e) => return Err(e.into()),
58 Self::Sending(future) => future.send_immediately()?,
59 Self::Finished => unreachable!(),
60 }
61
62 Ok(())
63 }
64 }
65
66 $(#[$metas])*
67 #[must_use = "futures do nothing unless polled"]
68 #[pin_project]
69 pub struct $name<
70 $($lifetime,)?
71 T: Transport,
72 > {
73 #[pin]
74 state: $state<$($lifetime,)? T>,
75 }
76
77 impl<$($lifetime,)? T: Transport> $name<$($lifetime,)? T> {
78 #[doc = concat!("Returns a `", stringify!($name), "` wrapping the given result.")]
79 pub fn from_untyped(result: Result<$future, EncodeError>) -> Self {
80 Self {
81 state: match result {
82 Err(error) => $state::EncodeError(error),
83 Ok(future) => $state::Sending(future),
84 },
85 }
86 }
87
88 pub fn encode(self) -> Result<$encoded<$($lifetime,)? T>, Error<T::Error>> {
92 Ok($encoded {
93 state: match self.state {
94 $state::EncodeError(error) => return Err(Error::Encode(error)),
95 state => state,
96 },
97 })
98 }
99
100 pub fn send_immediately(self) -> Result<(), Error<T::Error>>
112 where
113 T: NonBlockingTransport,
114 {
115 self.state.send_immediately()
116 }
117 }
118
119 impl<'a, T: Transport> Future for $name<$($lifetime,)? T> {
120 type Output = Result<(), Error<T::Error>>;
121
122 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
123 self.project().state.poll_state(cx)
124 }
125 }
126
127 #[doc = concat!("An encoded `", stringify!($name), "`.")]
128 #[must_use = "futures do nothing unless polled"]
132 #[pin_project]
133 pub struct $encoded<
134 $($lifetime,)?
135 T: Transport,
136 > {
137 #[pin]
138 state: $state<$($lifetime,)? T>,
139 }
140
141 impl<$($lifetime,)? T: Transport> Future for $encoded<$($lifetime,)? T> {
142 type Output = Result<(), Error<T::Error>>;
143
144 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
145 self.project().state.poll_state(cx)
146 }
147 }
148 }
149}
150
151define_send_future! {
152 SendFuture<'a, T: Transport>(fidl_next_protocol::SendFuture<'a, T>) => EncodedSendFuture {
154 state = SendFutureState,
155 proj = SendFutureProj,
156 own = SendFutureOwn,
157 }
158}
159
160define_send_future! {
161 RespondFuture<T: Transport>(fidl_next_protocol::RespondFuture<T>) => EncodedRespondFuture {
163 state = RespondFutureState,
164 proj = RespondFutureProj,
165 own = RespondFutureOwn,
166 }
167}