fidl_next_protocol/transport.rs
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.
4
5use core::error::Error;
6use core::pin::Pin;
7use core::task::{Context, Poll};
8
9use fidl_next_codec::{Decoder, Encoder};
10
11/// A transport layer which can send and receive messages.
12///
13/// The futures provided by this trait should be cancel-safe, which constrains
14/// their behavior:
15///
16/// - Operations should not partially complete.
17/// - Operations should only complete during polling.
18///
19/// `SendFuture` should return `Poll::Ready` with an error when polled after the
20/// transport is closed.
21pub trait Transport {
22 /// The error type for the transport.
23 type Error: Clone + Error + Send + Sync + 'static;
24
25 /// Splits the transport into shared and exclusive pieces.
26 fn split(self) -> (Self::Shared, Self::Exclusive);
27
28 /// The shared part of the transport. It is provided by shared reference
29 /// while sending and receiving. For an MPSC, this would contain a sender.
30 type Shared: Send + Sync;
31 /// The exclusive part of the transport. It is provided by mutable reference
32 /// only while receiving. For an MPSC, this would contain a receiver.
33 type Exclusive: Send;
34
35 /// The buffer type for sending.
36 type SendBuffer: Encoder + Send;
37 /// The future state for send operations.
38 type SendFutureState: Send;
39
40 /// Acquires an empty send buffer for the transport.
41 fn acquire(shared: &Self::Shared) -> Self::SendBuffer;
42
43 /// Begins sending a `SendBuffer` over this transport.
44 ///
45 /// Returns the state for a future which can be polled with `poll_send`.
46 fn begin_send(shared: &Self::Shared, buffer: Self::SendBuffer) -> Self::SendFutureState;
47
48 /// Polls a `SendFutureState` for completion with the shared part of the
49 /// transport.
50 ///
51 /// When ready, polling returns one of three values:
52 /// - `Ok(())` if the buffer was successfully sent.
53 /// - `Err(None)` if the connection was terminated normally (e.g. with
54 /// `PEER_CLOSED`).
55 /// - `Err(Some(error))` if the connection was terminated abnormally.
56 fn poll_send(
57 future: Pin<&mut Self::SendFutureState>,
58 cx: &mut Context<'_>,
59 shared: &Self::Shared,
60 ) -> Poll<Result<(), Option<Self::Error>>>;
61
62 /// The future state for receive operations.
63 type RecvFutureState: Send;
64 /// The buffer type for receivers.
65 type RecvBuffer: Decoder + Send;
66
67 /// Begins receiving a `RecvBuffer` over this transport.
68 ///
69 /// Returns the state for a future which can be polled with `poll_recv`.
70 fn begin_recv(shared: &Self::Shared, exclusive: &mut Self::Exclusive) -> Self::RecvFutureState;
71
72 /// Polls a `RecvFutureState` for completion with a receiver.
73 ///
74 /// When ready, polling returns one of three values:
75 /// - `Ok(buffer)` if `buffer` was successfully received.
76 /// - `Err(None)` if the connection was terminated normally (e.g. with
77 /// `PEER_CLOSED`).
78 /// - `Err(Some(error))` if the connection was terminated abnormally.
79 fn poll_recv(
80 future: Pin<&mut Self::RecvFutureState>,
81 cx: &mut Context<'_>,
82 shared: &Self::Shared,
83 exclusive: &mut Self::Exclusive,
84 ) -> Poll<Result<Self::RecvBuffer, Option<Self::Error>>>;
85}
86
87/// A transport layer which can send messages without blocking.
88///
89/// Because failed sends return immediately without waiting for an epitaph to be
90/// read, `send_immediately` may observe transport closure prematurely.
91///
92/// Non-blocking send operations cannot apply backpressure, which can cause
93/// memory exhaustion across the system. `NonBlockingTransport` is intended for
94/// use only while porting existing code.
95pub trait NonBlockingTransport: Transport {
96 /// Completes a `SendFutureState` with the shared part of the transport
97 /// without blocking.
98 fn send_immediately(
99 future_state: &mut Self::SendFutureState,
100 shared: &Self::Shared,
101 ) -> Result<(), Option<Self::Error>>;
102}