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;
6use core::mem::MaybeUninit;
7use core::{concat, stringify};
8
9use fidl_next_codec::{
10    Decode, DecodeError, Encodable, EncodableOption, Encode, EncodeError, EncodeOption,
11    EncodeOptionRef, EncodeRef, FromWire, FromWireOption, FromWireOptionRef, FromWireRef, Slot,
12    Wire, munge,
13};
14use fidl_next_protocol::{ProtocolError, Transport};
15
16use crate::{
17    Client, ClientSender, DispatchClientMessage, DispatchServerMessage, Executor, HasExecutor,
18    Server, ServerSender,
19};
20
21macro_rules! endpoint {
22    (
23        #[doc = $doc:literal]
24        $name:ident
25    ) => {
26        #[doc = $doc]
27        #[derive(Debug)]
28        #[repr(transparent)]
29        pub struct $name<
30            P,
31            #[cfg(feature = "fuchsia")]
32            T = zx::Channel,
33            #[cfg(not(feature = "fuchsia"))]
34            T,
35        > {
36            transport: T,
37            _protocol: PhantomData<P>,
38        }
39
40        unsafe impl<P, T: Send> Send for $name<P, T> {}
41
42        unsafe impl<P, T: Sync> Sync for $name<P, T> {}
43
44        // SAFETY:
45        // - `$name::Decoded<'de>` wraps a `T::Decoded<'de>`. Because `T: Wire`, `T::Decoded<'de>`
46        //   does not yield any references to decoded data that outlive `'de`. Therefore,
47        //   `$name::Decoded<'de>` also does not yield any references to decoded data that outlive
48        //   `'de`.
49        // - `$name` is `#[repr(transparent)]` over the transport `T`, and `zero_padding` calls
50        //   `T::zero_padding` on `transport`. `_protocol` is a ZST which does not have any padding
51        //   bytes to zero-initialize.
52        unsafe impl<P: 'static, T: Wire> Wire for $name<P, T> {
53            type Decoded<'de> = $name<P, T::Decoded<'de>>;
54
55            #[inline]
56            fn zero_padding(out: &mut MaybeUninit<Self>) {
57                munge!(let Self { transport, _protocol: _ } = out);
58                T::zero_padding(transport);
59            }
60        }
61
62        impl<P, T> $name<P, T> {
63            #[doc = concat!(
64                "Converts from `&",
65                stringify!($name),
66                "<P, T>` to `",
67                stringify!($name),
68                "<P, &T>`.",
69            )]
70            pub fn as_ref(&self) -> $name<P, &T> {
71                $name { transport: &self.transport, _protocol: PhantomData }
72            }
73
74            /// Returns a new endpoint over the given transport.
75            pub fn from_untyped(transport: T) -> Self {
76                Self { transport, _protocol: PhantomData }
77            }
78
79            /// Returns the underlying transport.
80            pub fn into_untyped(self) -> T {
81                self.transport
82            }
83
84            /// Returns the executor for the underlying transport.
85            pub fn executor(&self) -> T::Executor
86            where
87                T: HasExecutor,
88            {
89                self.transport.executor()
90            }
91        }
92
93        // SAFETY: `$name` is `#[repr(transparent)]` over the transport `T`, and `decode` calls
94        // `T::decode` on `transport`. `_protocol` is a ZST which does not have any data to decode.
95        unsafe impl<D, P, T> Decode<D> for $name<P, T>
96        where
97            D: ?Sized,
98            P: 'static,
99            T: Decode<D>,
100        {
101            fn decode(slot: Slot<'_, Self>, decoder: &mut D) -> Result<(), DecodeError> {
102                munge!(let Self { transport, _protocol: _ } = slot);
103                T::decode(transport, decoder)
104            }
105        }
106
107        impl<P, T> Encodable for $name<P, T>
108        where
109            T: Encodable,
110            P: 'static,
111        {
112            type Encoded = $name<P, T::Encoded>;
113        }
114
115        impl<P, T> EncodableOption for $name<P, T>
116        where
117            T: EncodableOption,
118            P: 'static,
119        {
120            type EncodedOption = $name<P, T::EncodedOption>;
121        }
122
123        // SAFETY: `$name` is `#[repr(transparent)]` over the transport `T`, and `encode` calls
124        // `T::encode` on `transport`. `_protocol` is a ZST which does not have any data to encode.
125        unsafe impl<E, P, T> Encode<E> for $name<P, T>
126        where
127            E: ?Sized,
128            P: 'static,
129            T: Encode<E>,
130        {
131            fn encode(
132                self,
133                encoder: &mut E,
134                out: &mut MaybeUninit<Self::Encoded>,
135            ) -> Result<(), EncodeError> {
136                munge!(let Self::Encoded { transport, _protocol: _ } = out);
137                self.transport.encode(encoder, transport)
138            }
139        }
140
141        // SAFETY: `$name` is `#[repr(transparent)]` over the transport `T`, and `encode_ref` calls
142        // `T::encode_ref` on `transport`. `_protocol` is a ZST which does not have any data to
143        // encode.
144        unsafe impl<E, P, T> EncodeRef<E> for $name<P, T>
145        where
146            E: ?Sized,
147            P: 'static,
148            T: EncodeRef<E>,
149        {
150            fn encode_ref(
151                &self,
152                encoder: &mut E,
153                out: &mut MaybeUninit<Self::Encoded>,
154            ) -> Result<(), EncodeError> {
155                self.as_ref().encode(encoder, out)
156            }
157        }
158
159        // SAFETY: `$name` is `#[repr(transparent)]` over the transport `T`, and `encode_option`
160        // calls `T::encode_option` on `transport`. `_protocol` is a ZST which does not have any
161        // data to encode.
162        unsafe impl<E, P, T> EncodeOption<E> for $name<P, T>
163        where
164            E: ?Sized,
165            P: 'static,
166            T: EncodeOption<E>,
167        {
168            fn encode_option(
169                this: Option<Self>,
170                encoder: &mut E,
171                out: &mut MaybeUninit<Self::EncodedOption>,
172            ) -> Result<(), EncodeError> {
173                munge!(let Self::EncodedOption { transport, _protocol: _ } = out);
174                T::encode_option(this.map(|this| this.transport), encoder, transport)
175            }
176        }
177
178        // SAFETY: `$name` is `#[repr(transparent)]` over the transport `T`, and `encode_option_ref`
179        // calls `T::encode_option_ref` on `transport`. `_protocol` is a ZST which does not have any
180        // data to encode.
181        unsafe impl<E, P, T> EncodeOptionRef<E> for $name<P, T>
182        where
183            E: ?Sized,
184            P: 'static,
185            T: EncodeOptionRef<E>,
186        {
187            fn encode_option_ref(
188                this: Option<&Self>,
189                encoder: &mut E,
190                out: &mut MaybeUninit<Self::EncodedOption>,
191            ) -> Result<(), EncodeError> {
192                munge!(let Self::EncodedOption { transport, _protocol: _ } = out);
193                T::encode_option_ref(this.map(|this| &this.transport), encoder, transport)
194            }
195        }
196
197        impl<P, T, U> FromWire<$name<P, U>> for $name<P, T>
198        where
199            T: FromWire<U>,
200        {
201            #[inline]
202            fn from_wire(wire: $name<P, U>) -> Self {
203                $name {
204                    transport: T::from_wire(wire.transport),
205                    _protocol: PhantomData,
206                }
207            }
208        }
209
210        impl<P, T, U> FromWireRef<$name<P, U>> for $name<P, T>
211        where
212            T: FromWireRef<U>,
213        {
214            #[inline]
215            fn from_wire_ref(wire: &$name<P, U>) -> Self {
216                $name {
217                    transport: T::from_wire_ref(&wire.transport),
218                    _protocol: PhantomData,
219                }
220            }
221        }
222
223        impl<P, T, U> FromWireOption<$name<P, U>> for $name<P, T>
224        where
225            P: 'static,
226            T: FromWireOption<U>,
227            U: Wire,
228        {
229            #[inline]
230            fn from_wire_option(wire: $name<P, U>) -> Option<Self> {
231                T::from_wire_option(wire.transport).map(|transport| $name {
232                    transport,
233                    _protocol: PhantomData,
234                })
235            }
236        }
237
238        impl<P, T, U> FromWireOptionRef<$name<P, U>> for $name<P, T>
239        where
240            P: 'static,
241            T: FromWireOptionRef<U>,
242            U: Wire,
243        {
244            #[inline]
245            fn from_wire_option_ref(wire: &$name<P, U>) -> Option<Self> {
246                T::from_wire_option_ref(&wire.transport).map(|transport| $name {
247                    transport,
248                    _protocol: PhantomData,
249                })
250            }
251        }
252    };
253}
254
255endpoint! {
256    /// The client end of a protocol.
257    ClientEnd
258}
259
260endpoint! {
261    /// The server end of a protocol.
262    ServerEnd
263}
264
265/// A client or server handler task.
266pub type HandlerTask<T, H, E = <T as HasExecutor>::Executor> =
267    <E as Executor>::Task<Result<H, ProtocolError<<T as Transport>::Error>>>;
268
269impl<P, T: Transport> ClientEnd<P, T> {
270    /// Spawns a client for the given client end with a handler on an executor.
271    ///
272    /// Returns the client sender and a join handle for the spawned task.
273    pub fn spawn_full_with_handler_on<H, E>(
274        self,
275        handler: H,
276        executor: &E,
277    ) -> (ClientSender<P, T>, HandlerTask<T, H, E>)
278    where
279        P: DispatchClientMessage<H, T>,
280        T: 'static,
281        H: Send + 'static,
282        E: Executor,
283    {
284        let client = Client::new(self);
285        let sender = client.sender().clone();
286        (sender, executor.spawn(client.run(handler)))
287    }
288
289    /// Spawns a client for the given client end with a handler on an executor.
290    ///
291    /// Returns the client sender.
292    pub fn spawn_with_handler_on<H, E>(self, handler: H, executor: &E) -> ClientSender<P, T>
293    where
294        P: DispatchClientMessage<H, T>,
295        T: 'static,
296        H: Send + 'static,
297        E: Executor,
298    {
299        let (sender, task) = Self::spawn_full_with_handler_on(self, handler, executor);
300        executor.detach(task);
301        sender
302    }
303
304    /// Spawns a client for the given client end with a handler on the default
305    /// executor for the transport.
306    ///
307    /// Returns the client sender and a join handle for the spawned task.
308    pub fn spawn_full_with_handler<H>(self, handler: H) -> (ClientSender<P, T>, HandlerTask<T, H>)
309    where
310        P: DispatchClientMessage<H, T>,
311        T: HasExecutor + 'static,
312        H: Send + 'static,
313    {
314        let executor = self.executor();
315        Self::spawn_full_with_handler_on(self, handler, &executor)
316    }
317
318    /// Spawns a client for the given client end with a handler on the default
319    /// executor for the transport.
320    ///
321    /// Returns the client sender.
322    pub fn spawn_with_handler<H>(self, handler: H) -> ClientSender<P, T>
323    where
324        P: DispatchClientMessage<H, T>,
325        T: HasExecutor + 'static,
326        H: Send + 'static,
327    {
328        let executor = self.executor();
329        Self::spawn_with_handler_on(self, handler, &executor)
330    }
331
332    /// Spawns a client for the given client end on an executor.
333    ///
334    /// The spawned client will ignore all incoming events. Returns the client
335    /// sender and a join handle for the spawned task.
336    pub fn spawn_full_on<E>(self, executor: &E) -> (ClientSender<P, T>, HandlerTask<T, (), E>)
337    where
338        P: 'static,
339        T: 'static,
340        E: Executor,
341    {
342        let client = Client::new(self);
343        let sender = client.sender().clone();
344        (sender, executor.spawn(client.run_sender()))
345    }
346
347    /// Spawns a client for the given client end on an executor.
348    ///
349    /// The spawned client will ignore all incoming events. Returns the client
350    /// sender.
351    pub fn spawn_on<E>(self, executor: &E) -> ClientSender<P, T>
352    where
353        P: 'static,
354        T: 'static,
355        E: Executor,
356    {
357        let (sender, task) = Self::spawn_full_on(self, executor);
358        executor.detach(task);
359        sender
360    }
361
362    /// Spawns a client for the given client end on the default executor for the
363    /// transport.
364    ///
365    /// The spawned client will ignore all incoming events. Returns the client
366    /// sender and a join handle for the spawned task.
367    pub fn spawn_full(self) -> (ClientSender<P, T>, HandlerTask<T, ()>)
368    where
369        P: 'static,
370        T: HasExecutor + 'static,
371    {
372        let executor = self.executor();
373        Self::spawn_full_on(self, &executor)
374    }
375
376    /// Spawns a client for the given client end on the default executor for the
377    /// transport.
378    ///
379    /// The spawned client will ignore all incoming events. Returns the client
380    /// sender.
381    pub fn spawn(self) -> ClientSender<P, T>
382    where
383        P: 'static,
384        T: HasExecutor + 'static,
385    {
386        let executor = self.executor();
387        Self::spawn_on(self, &executor)
388    }
389}
390
391impl<P, T: Transport> ServerEnd<P, T> {
392    /// Spawns a server for the given server end with a handler on an executor.
393    ///
394    /// Returns the join handle for the spawned task and the server sender.
395    pub fn spawn_full_on<H, E>(
396        self,
397        handler: H,
398        executor: &E,
399    ) -> (HandlerTask<T, H, E>, ServerSender<P, T>)
400    where
401        P: DispatchServerMessage<H, T>,
402        T: 'static,
403        H: Send + 'static,
404        E: Executor,
405    {
406        let server = Server::new(self);
407        let sender = server.sender().clone();
408        (executor.spawn(server.run(handler)), sender)
409    }
410
411    /// Spawns a server for the given server end with a handler on an executor.
412    ///
413    /// Returns the join handle for the spawned task.
414    pub fn spawn_on<H, E>(self, handler: H, executor: &E) -> HandlerTask<T, H, E>
415    where
416        P: DispatchServerMessage<H, T>,
417        T: 'static,
418        H: Send + 'static,
419        E: Executor,
420    {
421        executor.spawn(Server::new(self).run(handler))
422    }
423
424    /// Spawns a server for the given server end with a handler on the default
425    /// executor for the transport.
426    ///
427    /// Returns the join handle for the spawned task and the server sender.
428    pub fn spawn_full<H>(self, handler: H) -> (HandlerTask<T, H>, ServerSender<P, T>)
429    where
430        P: DispatchServerMessage<H, T>,
431        T: HasExecutor + 'static,
432        H: Send + 'static,
433    {
434        let executor = self.executor();
435        Self::spawn_full_on(self, handler, &executor)
436    }
437
438    /// Spawns a server for the given server end with a handler on the default
439    /// executor for the transport.
440    ///
441    /// Returns the join handle for the spawned task.
442    pub fn spawn<H>(self, handler: H) -> HandlerTask<T, H>
443    where
444        P: DispatchServerMessage<H, T>,
445        T: HasExecutor + 'static,
446        H: Send + 'static,
447    {
448        let executor = self.executor();
449        Self::spawn_on(self, handler, &executor)
450    }
451}