Skip to main content

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}