1#[cfg(feature = "alloc")]
27use core::future::Future;
28#[cfg(feature = "alloc")]
29use core::marker::PhantomData;
30#[cfg(feature = "rpc_try")]
31use core::ops::Try;
32#[cfg(feature = "alloc")]
33use core::pin::Pin;
34#[cfg(feature = "alloc")]
35use core::task::Poll;
36
37use crate::any_pointer;
38#[cfg(feature = "alloc")]
39use crate::private::capability::{ClientHook, ParamsHook, RequestHook, ResponseHook, ResultsHook};
40#[cfg(feature = "alloc")]
41use crate::traits::{Owned, Pipelined};
42#[cfg(feature = "alloc")]
43use crate::{Error, MessageSize};
44
45#[cfg(feature = "alloc")]
49pub type DynClientHook = dyn ClientHook;
50
51#[cfg(feature = "alloc")]
54#[must_use = "futures do nothing unless polled"]
55pub struct Promise<T, E> {
56 inner: PromiseInner<T, E>,
57}
58
59#[cfg(feature = "alloc")]
60enum PromiseInner<T, E> {
61 Immediate(Result<T, E>),
62 Deferred(Pin<alloc::boxed::Box<dyn Future<Output = core::result::Result<T, E>> + 'static>>),
63 Empty,
64}
65
66#[cfg(feature = "alloc")]
68impl<T, E> Unpin for PromiseInner<T, E> {}
69
70#[cfg(feature = "alloc")]
71impl<T, E> Promise<T, E> {
72 pub fn ok(value: T) -> Self {
73 Self {
74 inner: PromiseInner::Immediate(Ok(value)),
75 }
76 }
77
78 pub fn err(error: E) -> Self {
79 Self {
80 inner: PromiseInner::Immediate(Err(error)),
81 }
82 }
83
84 pub fn from_future<F>(f: F) -> Self
85 where
86 F: Future<Output = core::result::Result<T, E>> + 'static,
87 {
88 Self {
89 inner: PromiseInner::Deferred(alloc::boxed::Box::pin(f)),
90 }
91 }
92}
93
94#[cfg(feature = "alloc")]
95impl<T, E> Future for Promise<T, E> {
96 type Output = core::result::Result<T, E>;
97
98 fn poll(self: Pin<&mut Self>, cx: &mut ::core::task::Context) -> Poll<Self::Output> {
99 match self.get_mut().inner {
100 PromiseInner::Empty => panic!("Promise polled after done."),
101 ref mut imm @ PromiseInner::Immediate(_) => {
102 match core::mem::replace(imm, PromiseInner::Empty) {
103 PromiseInner::Immediate(r) => Poll::Ready(r),
104 _ => unreachable!(),
105 }
106 }
107 PromiseInner::Deferred(ref mut f) => f.as_mut().poll(cx),
108 }
109 }
110}
111
112#[cfg(feature = "alloc")]
113impl<T, E> From<Result<T, E>> for Promise<T, E> {
114 fn from(value: Result<T, E>) -> Self {
115 Self {
116 inner: PromiseInner::Immediate(value),
117 }
118 }
119}
120
121#[cfg(feature = "alloc")]
122#[cfg(feature = "rpc_try")]
123impl<T> core::ops::Try for Promise<T, crate::Error> {
124 type Output = Self;
125 type Residual = Result<core::convert::Infallible, crate::Error>;
126
127 fn from_output(output: Self::Output) -> Self {
128 output
129 }
130
131 fn branch(self) -> core::ops::ControlFlow<Self::Residual, Self::Output> {
132 unimplemented!();
133 }
134}
135
136#[cfg(feature = "alloc")]
137#[cfg(feature = "rpc_try")]
138impl<T> core::ops::FromResidual for Promise<T, crate::Error> {
139 fn from_residual(residual: <Self as Try>::Residual) -> Self {
140 match residual {
141 Ok(_) => unimplemented!(),
142 Err(e) => Self::err(e),
143 }
144 }
145}
146
147#[cfg(feature = "alloc")]
149#[must_use]
150pub struct RemotePromise<Results>
151where
152 Results: Pipelined + Owned + 'static,
153{
154 pub promise: Promise<Response<Results>, crate::Error>,
155 pub pipeline: Results::Pipeline,
156}
157
158#[cfg(feature = "alloc")]
160pub struct Response<Results> {
161 pub marker: PhantomData<Results>,
162 pub hook: alloc::boxed::Box<dyn ResponseHook>,
163}
164
165#[cfg(feature = "alloc")]
166impl<Results> Response<Results>
167where
168 Results: Pipelined + Owned,
169{
170 pub fn new(hook: alloc::boxed::Box<dyn ResponseHook>) -> Self {
171 Self {
172 marker: PhantomData,
173 hook,
174 }
175 }
176 pub fn get(&self) -> crate::Result<Results::Reader<'_>> {
177 self.hook.get()?.get_as()
178 }
179}
180
181#[cfg(feature = "alloc")]
183pub struct Request<Params, Results> {
184 pub marker: PhantomData<(Params, Results)>,
185 pub hook: alloc::boxed::Box<dyn RequestHook>,
186}
187
188#[cfg(feature = "alloc")]
189impl<Params, Results> Request<Params, Results>
190where
191 Params: Owned,
192{
193 pub fn new(hook: alloc::boxed::Box<dyn RequestHook>) -> Self {
194 Self {
195 hook,
196 marker: PhantomData,
197 }
198 }
199
200 pub fn get(&mut self) -> Params::Builder<'_> {
201 self.hook.get().get_as().unwrap()
202 }
203
204 pub fn set(&mut self, from: Params::Reader<'_>) -> crate::Result<()> {
205 self.hook.get().set_as(from)
206 }
207}
208
209#[cfg(feature = "alloc")]
210impl<Params, Results> Request<Params, Results>
211where
212 Results: Pipelined + Owned + 'static + Unpin,
213 <Results as Pipelined>::Pipeline: FromTypelessPipeline,
214{
215 pub fn send(self) -> RemotePromise<Results> {
216 let RemotePromise {
217 promise, pipeline, ..
218 } = self.hook.send();
219 let typed_promise = Promise::from_future(async move {
220 Ok(Response {
221 hook: promise.await?.hook,
222 marker: PhantomData,
223 })
224 });
225 RemotePromise {
226 promise: typed_promise,
227 pipeline: FromTypelessPipeline::new(pipeline),
228 }
229 }
230}
231
232#[cfg(feature = "alloc")]
234pub struct StreamingRequest<Params> {
235 pub marker: PhantomData<Params>,
236 pub hook: alloc::boxed::Box<dyn RequestHook>,
237}
238
239#[cfg(feature = "alloc")]
240impl<Params> StreamingRequest<Params>
241where
242 Params: Owned,
243{
244 pub fn get(&mut self) -> Params::Builder<'_> {
245 self.hook.get().get_as().unwrap()
246 }
247
248 pub fn send(self) -> Promise<(), Error> {
249 self.hook.send_streaming()
250 }
251}
252
253#[cfg(feature = "alloc")]
255pub struct Params<T> {
256 pub marker: PhantomData<T>,
257 pub hook: alloc::boxed::Box<dyn ParamsHook>,
258}
259
260#[cfg(feature = "alloc")]
261impl<T> Params<T> {
262 pub fn new(hook: alloc::boxed::Box<dyn ParamsHook>) -> Self {
263 Self {
264 marker: PhantomData,
265 hook,
266 }
267 }
268 pub fn get(&self) -> crate::Result<T::Reader<'_>>
269 where
270 T: Owned,
271 {
272 self.hook.get()?.get_as()
273 }
274}
275
276#[cfg(feature = "alloc")]
278pub struct Results<T> {
279 pub marker: PhantomData<T>,
280 pub hook: alloc::boxed::Box<dyn ResultsHook>,
281}
282
283#[cfg(feature = "alloc")]
284impl<T> Results<T>
285where
286 T: Owned,
287{
288 pub fn new(hook: alloc::boxed::Box<dyn ResultsHook>) -> Self {
289 Self {
290 marker: PhantomData,
291 hook,
292 }
293 }
294
295 pub fn get(&mut self) -> T::Builder<'_> {
296 self.hook.get().unwrap().get_as().unwrap()
297 }
298
299 pub fn set(&mut self, other: T::Reader<'_>) -> crate::Result<()> {
300 self.hook.get().unwrap().set_as(other)
301 }
302
303 pub fn set_pipeline(&mut self) -> crate::Result<()> {
307 self.hook.set_pipeline()
308 }
309}
310
311pub trait FromTypelessPipeline {
312 fn new(typeless: any_pointer::Pipeline) -> Self;
313}
314
315#[cfg(feature = "alloc")]
317pub trait FromClientHook {
318 fn new(hook: alloc::boxed::Box<dyn ClientHook>) -> Self;
320
321 fn into_client_hook(self) -> alloc::boxed::Box<dyn ClientHook>;
323
324 fn as_client_hook(&self) -> &dyn ClientHook;
326
327 fn cast_to<T: FromClientHook + Sized>(self) -> T
331 where
332 Self: Sized,
333 {
334 FromClientHook::new(self.into_client_hook())
335 }
336}
337
338#[cfg(feature = "alloc")]
339impl FromClientHook for alloc::boxed::Box<dyn ClientHook> {
340 fn new(hook: alloc::boxed::Box<dyn ClientHook>) -> Self {
341 hook
342 }
343
344 fn into_client_hook(self) -> alloc::boxed::Box<dyn ClientHook> {
345 self
346 }
347
348 fn as_client_hook(&self) -> &dyn ClientHook {
349 self.as_ref()
350 }
351}
352
353#[cfg(feature = "alloc")]
355pub struct Client {
356 pub hook: alloc::boxed::Box<dyn ClientHook>,
357}
358
359#[cfg(feature = "alloc")]
360impl Client {
361 pub fn new(hook: alloc::boxed::Box<dyn ClientHook>) -> Self {
362 Self { hook }
363 }
364
365 pub fn new_call<Params, Results>(
366 &self,
367 interface_id: u64,
368 method_id: u16,
369 size_hint: Option<MessageSize>,
370 ) -> Request<Params, Results> {
371 let typeless = self.hook.new_call(interface_id, method_id, size_hint);
372 Request {
373 hook: typeless.hook,
374 marker: PhantomData,
375 }
376 }
377
378 pub fn new_streaming_call<Params>(
379 &self,
380 interface_id: u64,
381 method_id: u16,
382 size_hint: Option<MessageSize>,
383 ) -> StreamingRequest<Params> {
384 let typeless = self.hook.new_call(interface_id, method_id, size_hint);
385 StreamingRequest {
386 hook: typeless.hook,
387 marker: PhantomData,
388 }
389 }
390
391 pub fn when_resolved(&self) -> Promise<(), Error> {
397 self.hook.when_resolved()
398 }
399}
400
401#[cfg(feature = "alloc")]
402impl FromClientHook for Client {
403 fn new(hook: alloc::boxed::Box<dyn ClientHook>) -> Self {
404 Client::new(hook)
405 }
406
407 fn into_client_hook(self) -> alloc::boxed::Box<dyn ClientHook> {
408 self.hook
409 }
410
411 fn as_client_hook(&self) -> &dyn ClientHook {
412 self.hook.as_ref()
413 }
414}
415
416#[cfg(feature = "alloc")]
417impl Clone for Client {
418 fn clone(&self) -> Self {
419 Self {
420 hook: self.hook.add_ref(),
421 }
422 }
423}
424
425#[cfg(feature = "alloc")]
427pub struct DispatchCallResult {
428 pub promise: Promise<(), Error>,
430
431 pub is_streaming: bool,
435}
436
437#[cfg(feature = "alloc")]
438impl DispatchCallResult {
439 pub fn new(promise: Promise<(), Error>, is_streaming: bool) -> Self {
440 Self {
441 promise,
442 is_streaming,
443 }
444 }
445}
446
447#[cfg(feature = "alloc")]
449pub trait Server {
450 fn dispatch_call(
451 &mut self,
452 interface_id: u64,
453 method_id: u16,
454 params: Params<any_pointer::Owned>,
455 results: Results<any_pointer::Owned>,
456 ) -> DispatchCallResult;
457}
458
459#[cfg(feature = "alloc")]
461pub trait FromServer<S>: FromClientHook {
462 type Dispatch: Server + 'static + core::ops::DerefMut<Target = S>;
464
465 fn from_server(s: S) -> Self::Dispatch;
466}
467
468#[cfg(feature = "alloc")]
471pub async fn get_resolved_cap<C: FromClientHook>(cap: C) -> C {
472 let mut hook = cap.into_client_hook();
473 let _ = hook.when_resolved().await;
474 while let Some(resolved) = hook.get_resolved() {
475 hook = resolved;
476 }
477 FromClientHook::new(hook)
478}