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