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, FromWire, FromWireOption, FromWireOptionRef, FromWireRef, Slot, Wire,
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<
23 P,
24 #[cfg(feature = "fuchsia")]
25 T = zx::Channel,
26 #[cfg(not(feature = "fuchsia"))]
27 T,
28 > {
29 transport: T,
30 _protocol: PhantomData<P>,
31 }
32
33 unsafe impl<P: 'static, T: Wire> Wire for $name<P, T> {
42 type Decoded<'de> = $name<P, T::Decoded<'de>>;
43
44 #[inline]
45 fn zero_padding(out: &mut MaybeUninit<Self>) {
46 munge!(let Self { transport, _protocol: _ } = out);
47 T::zero_padding(transport);
48 }
49 }
50
51 impl<P, T> $name<P, T> {
52 #[doc = concat!(
53 "Converts from `&",
54 stringify!($name),
55 "<P, T>` to `",
56 stringify!($name),
57 "<P, &T>`.",
58 )]
59 pub fn as_ref(&self) -> $name<P, &T> {
60 $name { transport: &self.transport, _protocol: PhantomData }
61 }
62
63 pub fn from_untyped(transport: T) -> Self {
65 Self { transport, _protocol: PhantomData }
66 }
67
68 pub fn into_untyped(self) -> T {
70 self.transport
71 }
72 }
73
74 unsafe impl<D, P, T> Decode<D> for $name<P, T>
77 where
78 D: ?Sized,
79 P: 'static,
80 T: Decode<D>,
81 {
82 fn decode(slot: Slot<'_, Self>, decoder: &mut D) -> Result<(), DecodeError> {
83 munge!(let Self { transport, _protocol: _ } = slot);
84 T::decode(transport, decoder)
85 }
86 }
87
88 impl<P, T> Encodable for $name<P, T>
89 where
90 T: Encodable,
91 P: 'static,
92 {
93 type Encoded = $name<P, T::Encoded>;
94 }
95
96 impl<P, T> EncodableOption for $name<P, T>
97 where
98 T: EncodableOption,
99 P: 'static,
100 {
101 type EncodedOption = $name<P, T::EncodedOption>;
102 }
103
104 unsafe impl<E, P, T> Encode<E> for $name<P, T>
107 where
108 E: ?Sized,
109 P: 'static,
110 T: Encode<E>,
111 {
112 fn encode(
113 self,
114 encoder: &mut E,
115 out: &mut MaybeUninit<Self::Encoded>,
116 ) -> Result<(), EncodeError> {
117 munge!(let Self::Encoded { transport, _protocol: _ } = out);
118 self.transport.encode(encoder, transport)
119 }
120 }
121
122 unsafe impl<E, P, T> EncodeRef<E> for $name<P, T>
126 where
127 E: ?Sized,
128 P: 'static,
129 T: EncodeRef<E>,
130 {
131 fn encode_ref(
132 &self,
133 encoder: &mut E,
134 out: &mut MaybeUninit<Self::Encoded>,
135 ) -> Result<(), EncodeError> {
136 self.as_ref().encode(encoder, out)
137 }
138 }
139
140 unsafe impl<E, P, T> EncodeOption<E> for $name<P, T>
144 where
145 E: ?Sized,
146 P: 'static,
147 T: EncodeOption<E>,
148 {
149 fn encode_option(
150 this: Option<Self>,
151 encoder: &mut E,
152 out: &mut MaybeUninit<Self::EncodedOption>,
153 ) -> Result<(), EncodeError> {
154 munge!(let Self::EncodedOption { transport, _protocol: _ } = out);
155 T::encode_option(this.map(|this| this.transport), encoder, transport)
156 }
157 }
158
159 impl<P, T, U> FromWire<$name<P, U>> for $name<P, T>
160 where
161 T: FromWire<U>,
162 {
163 #[inline]
164 fn from_wire(wire: $name<P, U>) -> Self {
165 $name {
166 transport: T::from_wire(wire.transport),
167 _protocol: PhantomData,
168 }
169 }
170 }
171
172 impl<P, T, U> FromWireRef<$name<P, U>> for $name<P, T>
173 where
174 T: FromWireRef<U>,
175 {
176 #[inline]
177 fn from_wire_ref(wire: &$name<P, U>) -> Self {
178 $name {
179 transport: T::from_wire_ref(&wire.transport),
180 _protocol: PhantomData,
181 }
182 }
183 }
184
185 impl<P, T, U> FromWireOption<$name<P, U>> for $name<P, T>
186 where
187 P: 'static,
188 T: FromWireOption<U>,
189 U: Wire,
190 {
191 #[inline]
192 fn from_wire_option(wire: $name<P, U>) -> Option<Self> {
193 T::from_wire_option(wire.transport).map(|transport| $name {
194 transport,
195 _protocol: PhantomData,
196 })
197 }
198 }
199
200 impl<P, T, U> FromWireOptionRef<$name<P, U>> for $name<P, T>
201 where
202 P: 'static,
203 T: FromWireOptionRef<U>,
204 U: Wire,
205 {
206 #[inline]
207 fn from_wire_option_ref(wire: &$name<P, U>) -> Option<Self> {
208 T::from_wire_option_ref(&wire.transport).map(|transport| $name {
209 transport,
210 _protocol: PhantomData,
211 })
212 }
213 }
214
215 #[cfg(feature = "compat")]
216 impl<P1, P2, T> From<$name<P1, T>> for ::fidl::endpoints::$name<P2>
217 where
218 ::fidl::Channel: From<T>,
219 P2: From<P1>,
220 {
221 fn from(from: $name<P1, T>) -> Self {
222 Self::new(from.transport.into())
223 }
224 }
225 };
226}
227
228endpoint! {
229 ClientEnd
231}
232
233endpoint! {
234 ServerEnd
236}