1use core::marker::PhantomData;
6use core::mem::MaybeUninit;
7use core::{concat, stringify};
8
9use fidl_next_codec::{
10 munge, Decode, DecodeError, Encodable, EncodableOption, Encode, EncodeError, EncodeOption,
11 EncodeRef, Slot, TakeFrom, ZeroPadding,
12};
13
14macro_rules! endpoint {
15 (
16 #[doc = $doc:literal]
17 $name:ident
18 ) => {
19 #[doc = $doc]
20 #[derive(Debug)]
21 #[repr(transparent)]
22 pub struct $name<T, P> {
23 transport: T,
24 _protocol: PhantomData<P>,
25 }
26
27 unsafe impl<T: ZeroPadding, P> ZeroPadding for $name<T, P> {
31 #[inline]
32 fn zero_padding(out: &mut MaybeUninit<Self>) {
33 munge!(let Self { transport, _protocol: _ } = out);
34 T::zero_padding(transport);
35 }
36 }
37
38 impl<T, P> $name<T, P> {
39 #[doc = concat!(
40 "Converts from `&",
41 stringify!($name),
42 "<T, P>` to `",
43 stringify!($name),
44 "<&T, P>`.",
45 )]
46 pub fn as_ref(&self) -> $name<&T, P> {
47 $name { transport: &self.transport, _protocol: PhantomData }
48 }
49
50 pub fn from_untyped(transport: T) -> Self {
52 Self { transport, _protocol: PhantomData }
53 }
54
55 pub fn into_untyped(self) -> T {
57 self.transport
58 }
59 }
60
61 unsafe impl<D, T, P> Decode<D> for $name<T, P>
64 where
65 D: ?Sized,
66 T: Decode<D>,
67 {
68 fn decode(slot: Slot<'_, Self>, decoder: &mut D) -> Result<(), DecodeError> {
69 munge!(let Self { transport, _protocol: _ } = slot);
70 T::decode(transport, decoder)
71 }
72 }
73
74 impl<T, P> Encodable for $name<T, P>
75 where
76 T: Encodable,
77 {
78 type Encoded = $name<T::Encoded, P>;
79 }
80
81 impl<T, P> EncodableOption for $name<T, P>
82 where
83 T: EncodableOption,
84 {
85 type EncodedOption = $name<T::EncodedOption, P>;
86 }
87
88 unsafe impl<E, T, P> Encode<E> for $name<T, P>
91 where
92 E: ?Sized,
93 T: Encode<E>,
94 {
95 fn encode(
96 self,
97 encoder: &mut E,
98 out: &mut MaybeUninit<Self::Encoded>,
99 ) -> Result<(), EncodeError> {
100 munge!(let Self::Encoded { transport, _protocol: _ } = out);
101 self.transport.encode(encoder, transport)
102 }
103 }
104
105 unsafe impl<E, T, P> EncodeRef<E> for $name<T, P>
109 where
110 E: ?Sized,
111 T: EncodeRef<E>,
112 {
113 fn encode_ref(
114 &self,
115 encoder: &mut E,
116 out: &mut MaybeUninit<Self::Encoded>,
117 ) -> Result<(), EncodeError> {
118 self.as_ref().encode(encoder, out)
119 }
120 }
121
122 unsafe impl<E, T, P> EncodeOption<E> for $name<T, P>
126 where
127 E: ?Sized,
128 T: EncodeOption<E>,
129 {
130 fn encode_option(
131 this: Option<Self>,
132 encoder: &mut E,
133 out: &mut MaybeUninit<Self::EncodedOption>,
134 ) -> Result<(), EncodeError> {
135 munge!(let Self::EncodedOption { transport, _protocol: _ } = out);
136 T::encode_option(this.map(|this| this.transport), encoder, transport)
137 }
138 }
139
140 impl<T, P, U> TakeFrom<$name<U, P>> for $name<T, P>
141 where
142 T: TakeFrom<U>,
143 {
144 fn take_from(from: &$name<U, P>) -> Self {
145 Self { transport: T::take_from(&from.transport), _protocol: PhantomData }
146 }
147 }
148
149 impl<T, P, U> TakeFrom<$name<U, P>> for Option<$name<T, P>>
150 where
151 Option<T>: TakeFrom<U>,
152 {
153 fn take_from(from: &$name<U, P>) -> Self {
154 Option::<T>::take_from(&from.transport)
155 .map(|transport| $name { transport, _protocol: PhantomData })
156 }
157 }
158
159 #[cfg(feature = "compat")]
160 impl<T, P1, P2> TakeFrom<$name<T, P1>> for ::fidl::endpoints::$name<P2>
161 where
162 ::fidl::Channel: TakeFrom<T>,
163 P2: TakeFrom<P1>,
164 {
165 fn take_from(from: &$name<T, P1>) -> Self {
166 Self::new(::fidl::Channel::take_from(&from.transport))
167 }
168 }
169
170 #[cfg(feature = "compat")]
171 impl<T, P1, P2> TakeFrom<$name<T, P1>> for Option<::fidl::endpoints::$name<P2>>
172 where
173 Option<::fidl::Channel>: TakeFrom<T>,
174 P2: TakeFrom<P1>,
175 {
176 fn take_from(from: &$name<T, P1>) -> Self {
177 Option::<::fidl::Channel>::take_from(&from.transport)
178 .map(::fidl::endpoints::$name::new)
179 }
180 }
181 };
182}
183
184endpoint! {
185 ClientEnd
187}
188
189endpoint! {
190 ServerEnd
192}