fidl_next_bind/
fuchsia_async.rs

1// Copyright 2025 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5//! FIDL bindings integration with fuchsia-async.
6
7use core::future::Future;
8use core::pin::Pin;
9use core::task::{Context, Poll};
10
11use fidl_next_protocol::mpsc::Mpsc as BaseMpsc;
12use fidl_next_protocol::{NonBlockingTransport, Transport};
13use fuchsia_async::{CancelableJoinHandle, Scope, ScopeHandle, Task};
14
15use crate::{ClientEnd, Executor, HasExecutor, RunsTransport, ServerEnd};
16
17/// A type representing the current fuchsia-async executor.
18pub struct FuchsiaAsync;
19
20impl Executor for FuchsiaAsync {
21    type JoinHandle<T>
22        = CancelableJoinHandle<T>
23    where
24        T: 'static;
25
26    fn spawn<F>(&self, future: F) -> Self::JoinHandle<F::Output>
27    where
28        F: Future + Send + 'static,
29        F::Output: Send + 'static,
30    {
31        #[allow(clippy::useless_conversion)]
32        CancelableJoinHandle::from(Task::spawn(future).detach_on_drop())
33    }
34}
35
36impl Executor for Scope {
37    type JoinHandle<T>
38        = CancelableJoinHandle<T>
39    where
40        T: 'static;
41
42    fn spawn<F>(&self, future: F) -> Self::JoinHandle<F::Output>
43    where
44        F: Future + Send + 'static,
45        F::Output: Send + 'static,
46    {
47        #[allow(clippy::useless_conversion)]
48        CancelableJoinHandle::from(self.compute(future).detach_on_drop())
49    }
50}
51
52impl Executor for ScopeHandle {
53    type JoinHandle<T>
54        = CancelableJoinHandle<T>
55    where
56        T: 'static;
57
58    fn spawn<F>(&self, future: F) -> Self::JoinHandle<F::Output>
59    where
60        F: Future + Send + 'static,
61        F::Output: Send + 'static,
62    {
63        #[allow(clippy::useless_conversion)]
64        CancelableJoinHandle::from(self.compute(future).detach_on_drop())
65    }
66}
67
68/// A paired mpsc transport which runs on fuchsia-async by default.
69pub struct Mpsc {
70    base: BaseMpsc,
71}
72
73impl Mpsc {
74    /// Creates client and server end mpscs which can communicate with each
75    /// other.
76    pub fn new<P>() -> (ClientEnd<P, Self>, ServerEnd<P, Self>) {
77        let (a, b) = BaseMpsc::new();
78        (ClientEnd::from_untyped(Self { base: a }), ServerEnd::from_untyped(Self { base: b }))
79    }
80}
81
82impl Transport for Mpsc {
83    type Error = <BaseMpsc as Transport>::Error;
84
85    fn split(self) -> (Self::Shared, Self::Exclusive) {
86        self.base.split()
87    }
88
89    type Shared = <BaseMpsc as Transport>::Shared;
90    type Exclusive = <BaseMpsc as Transport>::Exclusive;
91
92    type SendBuffer = <BaseMpsc as Transport>::SendBuffer;
93    type SendFutureState = <BaseMpsc as Transport>::SendFutureState;
94
95    fn acquire(shared: &Self::Shared) -> Self::SendBuffer {
96        BaseMpsc::acquire(shared)
97    }
98
99    fn begin_send(shared: &Self::Shared, buffer: Self::SendBuffer) -> Self::SendFutureState {
100        BaseMpsc::begin_send(shared, buffer)
101    }
102
103    fn poll_send(
104        future: Pin<&mut Self::SendFutureState>,
105        cx: &mut Context<'_>,
106        shared: &Self::Shared,
107    ) -> Poll<Result<(), Option<Self::Error>>> {
108        BaseMpsc::poll_send(future, cx, shared)
109    }
110
111    type RecvFutureState = <BaseMpsc as Transport>::RecvFutureState;
112    type RecvBuffer = <BaseMpsc as Transport>::RecvBuffer;
113
114    fn begin_recv(shared: &Self::Shared, exclusive: &mut Self::Exclusive) -> Self::RecvFutureState {
115        BaseMpsc::begin_recv(shared, exclusive)
116    }
117
118    fn poll_recv(
119        future: Pin<&mut Self::RecvFutureState>,
120        cx: &mut Context<'_>,
121        shared: &Self::Shared,
122        exclusive: &mut Self::Exclusive,
123    ) -> Poll<Result<Self::RecvBuffer, Option<Self::Error>>> {
124        BaseMpsc::poll_recv(future, cx, shared, exclusive)
125    }
126}
127
128impl NonBlockingTransport for Mpsc {
129    fn send_immediately(
130        future_state: &mut Self::SendFutureState,
131        shared: &Self::Shared,
132    ) -> Result<(), Option<Self::Error>> {
133        BaseMpsc::send_immediately(future_state, shared)
134    }
135}
136
137impl<E: RunsTransport<BaseMpsc>> RunsTransport<Mpsc> for E {}
138
139impl HasExecutor for Mpsc {
140    type Executor = FuchsiaAsync;
141
142    /// Returns a reference to the executor for this transport.
143    fn executor(&self) -> Self::Executor {
144        FuchsiaAsync
145    }
146}