fidl_next_bind/protocol.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 fidl_next_codec::{Decoded, wire as codec_wire};
6use fidl_next_protocol::{Flexibility, Transport, wire as protocol_wire};
7
8/// A FIDL protocol which has associated connection handles.
9///
10/// # Safety
11///
12/// The associated `Client` and `Server` types must be `#[repr(transparent)]`
13/// wrappers around `Client<T>` and `Server<T>` respectively.
14pub unsafe trait HasConnectionHandles<T> {
15 /// The client for the protocol. It must be a `#[repr(transparent)]` wrapper
16 /// around `Client<T>`.
17 type Client;
18
19 /// The server for the protocol. It must be a `#[repr(transparent)]` wrapper
20 /// around `Server<T>`.
21 type Server;
22}
23
24/// A discoverable FIDL protocol.
25pub trait Discoverable {
26 /// The service name to use to connect to this discoverable protocol.
27 const PROTOCOL_NAME: &'static str;
28}
29
30/// A method of a protocol.
31pub trait Method {
32 /// The ordinal associated with the method;
33 const ORDINAL: u64;
34
35 /// The flexibility of the method.
36 const FLEXIBILITY: Flexibility;
37
38 /// The protocol the method is a member of.
39 type Protocol;
40
41 /// The request payload for the method.
42 type Request;
43}
44
45/// A protocol method which has a response.
46pub trait TwoWayMethod: Method {
47 /// The response message for the method.
48 type Response: Response;
49}
50
51/// A protocol response message.
52///
53/// Two-way FIDL responses can be strict or flexible, and flexible responses
54/// wrap their responses in a FIDL union. This means that strict and flexible
55/// FIDL responses have different wire formats even though we treat flexible
56/// errors as protocol errors. So the protocol and bind layers get a little
57/// mixed up here.
58///
59/// To solve this, FIDL response types implement this `Response` trait and
60/// define how to "unwrap" themselves into their decoded `Payload` types. This
61/// eliminates an unnecessary `.0` field access that we'd have to do otherwise.
62pub trait Response {
63 /// The payload of the response.
64 type Payload;
65
66 /// Converts a `Decoded` of this type to a `Decoded` of its payload type.
67 fn into_payload<D>(decoded: Decoded<Self, D>) -> Decoded<Self::Payload, D>;
68}
69
70impl<T, E> Response for codec_wire::Result<'_, T, E> {
71 type Payload = Self;
72
73 fn into_payload<D>(decoded: Decoded<Self, D>) -> Decoded<Self::Payload, D> {
74 decoded
75 }
76}
77
78impl<T> Response for protocol_wire::Flexible<'_, T> {
79 type Payload = T;
80
81 fn into_payload<D>(decoded: Decoded<Self, D>) -> Decoded<Self::Payload, D> {
82 let (ptr, decoder) = Decoded::into_raw_parts(decoded);
83 let envelope = unsafe { codec_wire::Union::get_raw(ptr.cast()) };
84 let inner = unsafe { codec_wire::Envelope::as_ptr(envelope) };
85 unsafe { Decoded::new_unchecked(inner, decoder) }
86 }
87}
88
89impl<T> Response for protocol_wire::Strict<T> {
90 type Payload = T;
91
92 fn into_payload<D>(decoded: Decoded<Self, D>) -> Decoded<Self::Payload, D> {
93 let (ptr, decoder) = Decoded::into_raw_parts(decoded);
94 unsafe { Decoded::new_unchecked(ptr.cast(), decoder) }
95 }
96}
97
98/// A method which can be responded to with a single value.
99///
100/// For methods which return a result, this method implicitly returns `Ok` of
101/// the given response.
102pub trait Respond<R> {
103 /// The returned response type.
104 type Output;
105
106 /// Makes a response from the given input.
107 fn respond(response: R) -> Self::Output;
108}
109
110/// A method which can be responded `Err` to with a single value.
111pub trait RespondErr<R> {
112 /// The returned response type.
113 type Output;
114
115 /// Makes an `Err` response from the given input.
116 fn respond_err(response: R) -> Self::Output;
117}
118
119/// A protocol which has a default transport type.
120pub trait HasTransport {
121 /// The default transport type for this protocol.
122 type Transport: Transport;
123}