fidl_next_bind/
endpoint.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::marker::PhantomData;
6
7use fidl_next_codec::{
8    munge, Decode, DecodeError, Encodable, EncodableOption, Encode, EncodeError, EncodeOption,
9    Slot, TakeFrom, ZeroPadding,
10};
11
12macro_rules! endpoint {
13    (
14        #[doc = $doc:literal]
15        $name:ident
16    ) => {
17        #[doc = $doc]
18        #[derive(Debug)]
19        #[repr(transparent)]
20        pub struct $name<T, P> {
21            transport: T,
22            _protocol: PhantomData<P>,
23        }
24
25        unsafe impl<T: ZeroPadding, P> ZeroPadding for $name<T, P> {
26            #[inline]
27            unsafe fn zero_padding(ptr: *mut Self) {
28                unsafe {
29                    T::zero_padding(ptr.cast());
30                }
31            }
32        }
33
34        impl<T, P> $name<T, P> {
35            /// Returns a new endpoint over the given transport.
36            pub fn from_untyped(transport: T) -> Self {
37                Self { transport, _protocol: PhantomData }
38            }
39
40            /// Returns the underlying transport.
41            pub fn into_untyped(self) -> T {
42                self.transport
43            }
44        }
45
46        unsafe impl<D, T, P> Decode<D> for $name<T, P>
47        where
48            D: ?Sized,
49            T: Decode<D>,
50        {
51            fn decode(slot: Slot<'_, Self>, decoder: &mut D) -> Result<(), DecodeError> {
52                munge!(let Self { transport, _protocol: _ } = slot);
53                T::decode(transport, decoder)
54            }
55        }
56
57        impl<T, P> Encodable for $name<T, P>
58        where
59            T: Encodable,
60        {
61            type Encoded = $name<T::Encoded, P>;
62        }
63
64        impl<T, P> EncodableOption for $name<T, P>
65        where
66            T: EncodableOption,
67        {
68            type EncodedOption = $name<T::EncodedOption, P>;
69        }
70
71        impl<E, T, P> Encode<E> for $name<T, P>
72        where
73            E: ?Sized,
74            T: Encode<E>,
75        {
76            fn encode(
77                &mut self,
78                encoder: &mut E,
79                slot: Slot<'_, Self::Encoded>,
80            ) -> Result<(), EncodeError> {
81                munge!(let Self::Encoded { transport, _protocol: _ } = slot);
82                self.transport.encode(encoder, transport)
83            }
84        }
85
86        impl<E, T, P> EncodeOption<E> for $name<T, P>
87        where
88            E: ?Sized,
89            T: EncodeOption<E>,
90        {
91            fn encode_option(
92                this: Option<&mut Self>,
93                encoder: &mut E,
94                slot: Slot<'_, Self::EncodedOption>,
95            ) -> Result<(), EncodeError> {
96                munge!(let Self::EncodedOption { transport, _protocol: _ } = slot);
97                T::encode_option(this.map(|this| &mut this.transport), encoder, transport)
98            }
99        }
100
101        impl<T, P, U> TakeFrom<$name<U, P>> for $name<T, P>
102        where
103            T: TakeFrom<U>,
104        {
105            fn take_from(from: &$name<U, P>) -> Self {
106                Self { transport: T::take_from(&from.transport), _protocol: PhantomData }
107            }
108        }
109    };
110}
111
112endpoint! {
113    /// The client end of a protocol.
114    ClientEnd
115}
116
117endpoint! {
118    /// The server end of a protocol.
119    ServerEnd
120}