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::{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 Task<T>
22        = Task<T>
23    where
24        T: 'static;
25
26    fn spawn<F>(&self, future: F) -> Self::Task<F::Output>
27    where
28        F: Future + Send + 'static,
29        F::Output: Send + 'static,
30    {
31        Task::spawn(future)
32    }
33
34    fn detach<T: 'static>(&self, task: Self::Task<T>) {
35        drop(task.detach_on_drop());
36    }
37}
38
39impl Executor for Scope {
40    type Task<T>
41        = Task<T>
42    where
43        T: 'static;
44
45    fn spawn<F>(&self, future: F) -> Self::Task<F::Output>
46    where
47        F: Future + Send + 'static,
48        F::Output: Send + 'static,
49    {
50        self.compute(future)
51    }
52
53    fn detach<T: 'static>(&self, task: Self::Task<T>) {
54        drop(task.detach_on_drop());
55    }
56}
57
58impl Executor for ScopeHandle {
59    type Task<T>
60        = Task<T>
61    where
62        T: 'static;
63
64    fn spawn<F>(&self, future: F) -> Self::Task<F::Output>
65    where
66        F: Future + Send + 'static,
67        F::Output: Send + 'static,
68    {
69        self.compute(future)
70    }
71
72    fn detach<T: 'static>(&self, task: Self::Task<T>) {
73        drop(task.detach_on_drop());
74    }
75}
76
77/// A paired mpsc transport which runs on fuchsia-async by default.
78pub struct Mpsc {
79    base: BaseMpsc,
80}
81
82impl Mpsc {
83    /// Creates client and server end mpscs which can communicate with each
84    /// other.
85    pub fn new<P>() -> (ClientEnd<P, Self>, ServerEnd<P, Self>) {
86        let (a, b) = BaseMpsc::new();
87        (ClientEnd::from_untyped(Self { base: a }), ServerEnd::from_untyped(Self { base: b }))
88    }
89}
90
91impl Transport for Mpsc {
92    type Error = <BaseMpsc as Transport>::Error;
93
94    fn split(self) -> (Self::Shared, Self::Exclusive) {
95        self.base.split()
96    }
97
98    type Shared = <BaseMpsc as Transport>::Shared;
99    type Exclusive = <BaseMpsc as Transport>::Exclusive;
100
101    type SendBuffer = <BaseMpsc as Transport>::SendBuffer;
102    type SendFutureState = <BaseMpsc as Transport>::SendFutureState;
103
104    fn acquire(shared: &Self::Shared) -> Self::SendBuffer {
105        BaseMpsc::acquire(shared)
106    }
107
108    fn begin_send(shared: &Self::Shared, buffer: Self::SendBuffer) -> Self::SendFutureState {
109        BaseMpsc::begin_send(shared, buffer)
110    }
111
112    fn poll_send(
113        future: Pin<&mut Self::SendFutureState>,
114        cx: &mut Context<'_>,
115        shared: &Self::Shared,
116    ) -> Poll<Result<(), Option<Self::Error>>> {
117        BaseMpsc::poll_send(future, cx, shared)
118    }
119
120    type RecvFutureState = <BaseMpsc as Transport>::RecvFutureState;
121    type RecvBuffer = <BaseMpsc as Transport>::RecvBuffer;
122
123    fn begin_recv(shared: &Self::Shared, exclusive: &mut Self::Exclusive) -> Self::RecvFutureState {
124        BaseMpsc::begin_recv(shared, exclusive)
125    }
126
127    fn poll_recv(
128        future: Pin<&mut Self::RecvFutureState>,
129        cx: &mut Context<'_>,
130        shared: &Self::Shared,
131        exclusive: &mut Self::Exclusive,
132    ) -> Poll<Result<Self::RecvBuffer, Option<Self::Error>>> {
133        BaseMpsc::poll_recv(future, cx, shared, exclusive)
134    }
135}
136
137impl NonBlockingTransport for Mpsc {
138    fn send_immediately(
139        future_state: &mut Self::SendFutureState,
140        shared: &Self::Shared,
141    ) -> Result<(), Option<Self::Error>> {
142        BaseMpsc::send_immediately(future_state, shared)
143    }
144}
145
146impl<E: RunsTransport<BaseMpsc>> RunsTransport<Mpsc> for E {}
147
148impl HasExecutor for Mpsc {
149    type Executor = FuchsiaAsync;
150
151    /// Returns a reference to the executor for this transport.
152    fn executor(&self) -> Self::Executor {
153        FuchsiaAsync
154    }
155}