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,
12    IntoNatural, Slot, Wire, munge,
13};
14use fidl_next_protocol::{ProtocolError, Transport};
15
16use crate::{
17    Client, ClientDispatcher, DispatchClientMessage, DispatchServerMessage, Executor, HasExecutor,
18    Server, ServerDispatcher,
19};
20
21macro_rules! endpoint {
22    (
23        #[doc = $doc:literal]
24        $name:ident
25    ) => {
26        #[doc = $doc]
27        #[derive(Debug, PartialEq)]
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: IntoNatural> IntoNatural for $name<P, T> {
211            type Natural = $name<P, T::Natural>;
212        }
213
214        impl<P, T, U> FromWireRef<$name<P, U>> for $name<P, T>
215        where
216            T: FromWireRef<U>,
217        {
218            #[inline]
219            fn from_wire_ref(wire: &$name<P, U>) -> Self {
220                $name {
221                    transport: T::from_wire_ref(&wire.transport),
222                    _protocol: PhantomData,
223                }
224            }
225        }
226
227        impl<P, T, U> FromWireOption<$name<P, U>> for $name<P, T>
228        where
229            P: 'static,
230            T: FromWireOption<U>,
231            U: Wire,
232        {
233            #[inline]
234            fn from_wire_option(wire: $name<P, U>) -> Option<Self> {
235                T::from_wire_option(wire.transport).map(|transport| $name {
236                    transport,
237                    _protocol: PhantomData,
238                })
239            }
240        }
241
242        impl<P, T, U> FromWireOptionRef<$name<P, U>> for $name<P, T>
243        where
244            P: 'static,
245            T: FromWireOptionRef<U>,
246            U: Wire,
247        {
248            #[inline]
249            fn from_wire_option_ref(wire: &$name<P, U>) -> Option<Self> {
250                T::from_wire_option_ref(&wire.transport).map(|transport| $name {
251                    transport,
252                    _protocol: PhantomData,
253                })
254            }
255        }
256    };
257}
258
259endpoint! {
260    /// The client end of a protocol.
261    ClientEnd
262}
263
264endpoint! {
265    /// The server end of a protocol.
266    ServerEnd
267}
268
269/// A client or server handler task.
270pub type HandlerTask<T, H, E = <T as HasExecutor>::Executor> =
271    <E as Executor>::Task<Result<H, ProtocolError<<T as Transport>::Error>>>;
272
273impl<P, T: Transport> ClientEnd<P, T> {
274    /// Spawns a dispatcher for the given client end with a handler computed
275    /// from a closure on an executor.
276    ///
277    /// Returns the client and a join handle for the spawned task.
278    pub fn spawn_handler_full_on_with<H, E>(
279        self,
280        create_handler: impl FnOnce(Client<P, T>) -> H,
281        executor: &E,
282    ) -> (Client<P, T>, HandlerTask<T, H, E>)
283    where
284        P: DispatchClientMessage<H, T>,
285        T: 'static,
286        H: Send + 'static,
287        E: Executor,
288    {
289        let dispatcher = ClientDispatcher::new(self);
290        let client = dispatcher.client();
291        let handler = create_handler(client.clone());
292        (client, executor.spawn(dispatcher.run(handler)))
293    }
294
295    /// Spawns a dispatcher for the given client end with a handler on an
296    /// executor.
297    ///
298    /// Returns the client and a join handle for the spawned task.
299    pub fn spawn_handler_full_on<H, E>(
300        self,
301        handler: H,
302        executor: &E,
303    ) -> (Client<P, T>, HandlerTask<T, H, E>)
304    where
305        P: DispatchClientMessage<H, T>,
306        T: 'static,
307        H: Send + 'static,
308        E: Executor,
309    {
310        self.spawn_handler_full_on_with(|_| handler, executor)
311    }
312
313    /// Spawns a dispatcher for the given client end with a handler computed
314    /// from a closure on an executor.
315    ///
316    /// Returns the client.
317    pub fn spawn_handler_on_with<H, E>(
318        self,
319        create_handler: impl FnOnce(Client<P, T>) -> H,
320        executor: &E,
321    ) -> Client<P, T>
322    where
323        P: DispatchClientMessage<H, T>,
324        T: 'static,
325        H: Send + 'static,
326        E: Executor,
327    {
328        let (client, task) = Self::spawn_handler_full_on_with(self, create_handler, executor);
329        executor.detach(task);
330        client
331    }
332
333    /// Spawns a dispatcher for the given client end with a handler on an
334    /// executor.
335    ///
336    /// Returns the client.
337    pub fn spawn_handler_on<H, E>(self, handler: H, executor: &E) -> Client<P, T>
338    where
339        P: DispatchClientMessage<H, T>,
340        T: 'static,
341        H: Send + 'static,
342        E: Executor,
343    {
344        self.spawn_handler_on_with(|_| handler, executor)
345    }
346
347    /// Spawns a dispatcher for the given client end with a handler computed
348    /// from a closure on the default executor for the transport.
349    ///
350    /// Returns the client and a join handle for the spawned task.
351    pub fn spawn_handler_full_with<H>(
352        self,
353        create_handler: impl FnOnce(Client<P, T>) -> H,
354    ) -> (Client<P, T>, HandlerTask<T, H>)
355    where
356        P: DispatchClientMessage<H, T>,
357        T: HasExecutor + 'static,
358        H: Send + 'static,
359    {
360        let executor = self.executor();
361        Self::spawn_handler_full_on_with(self, create_handler, &executor)
362    }
363
364    /// Spawns a dispatcher for the given client end with a handler on the
365    /// default executor for the transport.
366    ///
367    /// Returns the client and a join handle for the spawned task.
368    pub fn spawn_handler_full<H>(self, handler: H) -> (Client<P, T>, HandlerTask<T, H>)
369    where
370        P: DispatchClientMessage<H, T>,
371        T: HasExecutor + 'static,
372        H: Send + 'static,
373    {
374        self.spawn_handler_full_with(|_| handler)
375    }
376
377    /// Spawns a dispatcher for the given client end with a handler computed
378    /// from a closure on the default executor for the transport.
379    ///
380    /// Returns the client.
381    pub fn spawn_handler_with<H>(
382        self,
383        create_handler: impl FnOnce(Client<P, T>) -> H,
384    ) -> Client<P, T>
385    where
386        P: DispatchClientMessage<H, T>,
387        T: HasExecutor + 'static,
388        H: Send + 'static,
389    {
390        let executor = self.executor();
391        Self::spawn_handler_on_with(self, create_handler, &executor)
392    }
393
394    /// Spawns a dispatcher for the given client end with a handler on the
395    /// default executor for the transport.
396    ///
397    /// Returns the client.
398    pub fn spawn_handler<H>(self, handler: H) -> Client<P, T>
399    where
400        P: DispatchClientMessage<H, T>,
401        T: HasExecutor + 'static,
402        H: Send + 'static,
403    {
404        self.spawn_handler_with(|_| handler)
405    }
406
407    /// Spawns a dispatcher for the given client end on an executor.
408    ///
409    /// The spawned dispatcher will ignore all incoming events. Returns the
410    /// client and a join handle for the spawned task.
411    pub fn spawn_full_on<E>(self, executor: &E) -> (Client<P, T>, HandlerTask<T, (), E>)
412    where
413        P: 'static,
414        T: 'static,
415        E: Executor,
416    {
417        let dispatcher = ClientDispatcher::new(self);
418        let client = dispatcher.client();
419        (client, executor.spawn(dispatcher.run_client()))
420    }
421
422    /// Spawns a dispatcher for the given client end on an executor.
423    ///
424    /// The spawned dispatcher will ignore all incoming events. Returns the
425    /// client.
426    pub fn spawn_on<E>(self, executor: &E) -> Client<P, T>
427    where
428        P: 'static,
429        T: 'static,
430        E: Executor,
431    {
432        let (client, task) = Self::spawn_full_on(self, executor);
433        executor.detach(task);
434        client
435    }
436
437    /// Spawns a dispatcher for the given client end on the default executor for
438    /// the transport.
439    ///
440    /// The spawned dispatcher will ignore all incoming events. Returns the
441    /// client and a join handle for the spawned task.
442    pub fn spawn_full(self) -> (Client<P, T>, HandlerTask<T, ()>)
443    where
444        P: 'static,
445        T: HasExecutor + 'static,
446    {
447        let executor = self.executor();
448        Self::spawn_full_on(self, &executor)
449    }
450
451    /// Spawns a dispatcher for the given client end on the default executor for
452    /// the transport.
453    ///
454    /// The spawned dispatcher will ignore all incoming events. Returns the
455    /// client.
456    pub fn spawn(self) -> Client<P, T>
457    where
458        P: 'static,
459        T: HasExecutor + 'static,
460    {
461        let executor = self.executor();
462        Self::spawn_on(self, &executor)
463    }
464}
465
466impl<P, T: Transport> ServerEnd<P, T> {
467    /// Spawns a dispatcher for the given server end with a handler computed
468    /// from a closure on an executor.
469    ///
470    /// Returns the join handle for the spawned task and the server.
471    pub fn spawn_full_on_with<H, E>(
472        self,
473        create_handler: impl FnOnce(Server<P, T>) -> H,
474        executor: &E,
475    ) -> (HandlerTask<T, H, E>, Server<P, T>)
476    where
477        P: DispatchServerMessage<H, T>,
478        T: 'static,
479        H: Send + 'static,
480        E: Executor,
481    {
482        let dispatcher = ServerDispatcher::new(self);
483        let server = dispatcher.server();
484        let handler = create_handler(server.clone());
485        (executor.spawn(dispatcher.run(handler)), server)
486    }
487
488    /// Spawns a dispatcher for the given server end with a handler on an
489    /// executor.
490    ///
491    /// Returns the join handle for the spawned task and the server.
492    pub fn spawn_full_on<H, E>(
493        self,
494        handler: H,
495        executor: &E,
496    ) -> (HandlerTask<T, H, E>, Server<P, T>)
497    where
498        P: DispatchServerMessage<H, T>,
499        T: 'static,
500        H: Send + 'static,
501        E: Executor,
502    {
503        self.spawn_full_on_with(|_| handler, executor)
504    }
505
506    /// Spawns a dispatcher for the given server end with a handler computed
507    /// from a closure on an executor.
508    ///
509    /// Returns the join handle for the spawned task.
510    pub fn spawn_on_with<H, E>(
511        self,
512        create_handler: impl FnOnce(Server<P, T>) -> H,
513        executor: &E,
514    ) -> HandlerTask<T, H, E>
515    where
516        P: DispatchServerMessage<H, T>,
517        T: 'static,
518        H: Send + 'static,
519        E: Executor,
520    {
521        let dispatcher = ServerDispatcher::new(self);
522        let handler = create_handler(dispatcher.server());
523        executor.spawn(dispatcher.run(handler))
524    }
525
526    /// Spawns a dispatcher for the given server end with a handler on an
527    /// executor.
528    ///
529    /// Returns the join handle for the spawned task.
530    pub fn spawn_on<H, E>(self, handler: H, executor: &E) -> HandlerTask<T, H, E>
531    where
532        P: DispatchServerMessage<H, T>,
533        T: 'static,
534        H: Send + 'static,
535        E: Executor,
536    {
537        self.spawn_on_with(|_| handler, executor)
538    }
539
540    /// Spawns a dispatcher for the given server end with a handler computed
541    /// from a closure on the default executor for the transport.
542    ///
543    /// Returns the join handle for the spawned task and the server.
544    pub fn spawn_full_with<H>(
545        self,
546        create_handler: impl FnOnce(Server<P, T>) -> H,
547    ) -> (HandlerTask<T, H>, Server<P, T>)
548    where
549        P: DispatchServerMessage<H, T>,
550        T: HasExecutor + 'static,
551        H: Send + 'static,
552    {
553        let executor = self.executor();
554        Self::spawn_full_on_with(self, create_handler, &executor)
555    }
556
557    /// Spawns a dispatcher for the given server end with a handler on the
558    /// default executor for the transport.
559    ///
560    /// Returns the join handle for the spawned task and the server.
561    pub fn spawn_full<H>(self, handler: H) -> (HandlerTask<T, H>, Server<P, T>)
562    where
563        P: DispatchServerMessage<H, T>,
564        T: HasExecutor + 'static,
565        H: Send + 'static,
566    {
567        self.spawn_full_with(|_| handler)
568    }
569
570    /// Spawns a dispatcher for the given server end with a handler computed
571    /// from a closure on the default executor for the transport.
572    ///
573    /// Returns the join handle for the spawned task.
574    pub fn spawn_with<H>(self, create_handler: impl FnOnce(Server<P, T>) -> H) -> HandlerTask<T, H>
575    where
576        P: DispatchServerMessage<H, T>,
577        T: HasExecutor + 'static,
578        H: Send + 'static,
579    {
580        let executor = self.executor();
581        Self::spawn_on_with(self, create_handler, &executor)
582    }
583
584    /// Spawns a dispatcher for the given server end with a handler on the
585    /// default executor for the transport.
586    ///
587    /// Returns the join handle for the spawned task.
588    pub fn spawn<H>(self, handler: H) -> HandlerTask<T, H>
589    where
590        P: DispatchServerMessage<H, T>,
591        T: HasExecutor + 'static,
592        H: Send + 'static,
593    {
594        self.spawn_with(|_| handler)
595    }
596}