1// Copyright 2024 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.
45use core::error::Error;
6use core::future::Future;
7use core::pin::Pin;
8use core::task::{Context, Poll};
910use fidl_next_codec::{Decoder, Encoder};
1112// Design philosophy:
13//
14// - Fan-out is best handled by protocols (via executors)
15// - Fan-in is best handled by transports (in whatever way is appropriate)
16//
17// Therefore:
18//
19// - A transport may only have one receiver at a time. To parallelize, spawn a future for each
20// message.
21// - A transport may have many senders at a time. If a transport is serialized, then it must
22// determine the best way to enqueue operations.
2324/// A transport layer which can send and receive messages.
25///
26/// The futures provided by this trait should be cancel-safe, which constrains their behavior:
27///
28/// - Operations should not partially complete.
29/// - Operations should only complete during polling.
30///
31/// `SendFuture` should return an `Poll::Ready` with an error when polled after the transport is
32/// closed.
33pub trait Transport {
34/// The error type for the transport.
35type Error: Error + Send + Sync + 'static;
3637/// Splits the transport into a sender and receiver.
38fn split(self) -> (Self::Sender, Self::Receiver);
3940/// The sender half of the transport. Dropping all of the senders for a transport should close
41 /// the transport.
42type Sender: Send + Sync + Clone;
43/// The buffer type for senders.
44type SendBuffer: Encoder + Send;
45/// The future state for send operations.
46type SendFutureState: Send;
4748/// Acquires an empty send buffer for the transport.
49fn acquire(sender: &Self::Sender) -> Self::SendBuffer;
50/// Begins sending a `SendBuffer` over this transport.
51 ///
52 /// Returns the state for a future which can be polled with `poll_send`.
53fn begin_send(sender: &Self::Sender, buffer: Self::SendBuffer) -> Self::SendFutureState;
54/// Polls a `SendFutureState` for completion with a sender.
55fn poll_send(
56 future: Pin<&mut Self::SendFutureState>,
57 cx: &mut Context<'_>,
58 sender: &Self::Sender,
59 ) -> Poll<Result<(), Self::Error>>;
60/// Closes the transport.
61fn close(sender: &Self::Sender);
6263/// The receiver half of the transport.
64type Receiver: Send;
65/// The future state for receive operations.
66type RecvFutureState: Send;
67/// The buffer type for receivers.
68type RecvBuffer: Decoder + Send;
6970/// Begins receiving a `RecvBuffer` over this transport.
71 ///
72 /// Returns the state for a future which can be polled with `poll_recv`.
73fn begin_recv(receiver: &mut Self::Receiver) -> Self::RecvFutureState;
74/// Polls a `RecvFutureState` for completion with a receiver.
75fn poll_recv(
76 future: Pin<&mut Self::RecvFutureState>,
77 cx: &mut Context<'_>,
78 receiver: &mut Self::Receiver,
79 ) -> Poll<Result<Option<Self::RecvBuffer>, Self::Error>>;
80}
8182/// Helper methods for `Transport`.
83pub trait TransportExt: Transport {
84/// Sends an encoded message over the transport.
85fn send(sender: &Self::Sender, buffer: Self::SendBuffer) -> SendFuture<'_, Self> {
86let future_state = Self::begin_send(sender, buffer);
87 SendFuture { sender, future_state }
88 }
8990/// Receives an encoded message over the transport.
91fn recv(receiver: &mut Self::Receiver) -> RecvFuture<'_, Self> {
92let future_state = Self::begin_recv(receiver);
93 RecvFuture { receiver, future_state }
94 }
95}
9697impl<T: Transport + ?Sized> TransportExt for T {}
9899/// A future which sends an encoded message over the transport.
100#[must_use = "futures do nothing unless polled"]
101pub struct SendFuture<'s, T: Transport + ?Sized> {
102 sender: &'s T::Sender,
103 future_state: T::SendFutureState,
104}
105106impl<T: Transport> Future for SendFuture<'_, T> {
107type Output = Result<(), T::Error>;
108109fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
110let this = unsafe { Pin::into_inner_unchecked(self) };
111let future_state = unsafe { Pin::new_unchecked(&mut this.future_state) };
112 T::poll_send(future_state, cx, this.sender)
113 }
114}
115116/// A future which receives an encoded message over the transport.
117#[must_use = "futures do nothing unless polled"]
118pub struct RecvFuture<'r, T: Transport + ?Sized> {
119 receiver: &'r mut T::Receiver,
120 future_state: T::RecvFutureState,
121}
122123impl<T: Transport> Future for RecvFuture<'_, T> {
124type Output = Result<Option<T::RecvBuffer>, T::Error>;
125126fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
127let this = unsafe { Pin::into_inner_unchecked(self) };
128let future_state = unsafe { Pin::new_unchecked(&mut this.future_state) };
129 T::poll_recv(future_state, cx, this.receiver)
130 }
131}