Skip to main content

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    Constrained, Decode, DecodeError, Encode, EncodeError, EncodeOption, FromWire, FromWireOption,
11    FromWireOptionRef, FromWireRef, IntoNatural, Slot, ValidationError, Wire, munge,
12};
13use fidl_next_protocol::{ProtocolError, Transport};
14
15use crate::{
16    Client, ClientDispatcher, DispatchClientMessage, DispatchLocalClientMessage,
17    DispatchLocalServerMessage, DispatchServerMessage, Executor, HasExecutor, HasTransport,
18    IgnoreEvents, LocalExecutor, Server, ServerDispatcher,
19};
20
21/// An adapter that allows a non-local handler to be run on a local executor.
22pub struct Local<H>(pub H);
23
24macro_rules! endpoint {
25    (
26        #[doc = $doc:literal]
27        $name:ident
28    ) => {
29        #[doc = $doc]
30        #[derive(Debug, PartialEq)]
31        #[repr(transparent)]
32        pub struct $name<
33            P,
34            T = <P as HasTransport>::Transport,
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        impl<P, T: Constrained> Constrained for $name<P, T> {
45            type Constraint = T::Constraint;
46
47            fn validate(slot: Slot<'_, Self>, constraint: Self::Constraint) -> Result<(), ValidationError> {
48                munge!(let Self { transport, _protocol: _ } = slot);
49
50                T::validate(transport, constraint)
51            }
52        }
53
54        // SAFETY:
55        // - `$name::Owned<'de>` wraps a `T::Owned<'de>`. Because `T: Wire`,
56        //   `T::Owned<'de>` does not yield any references to decoded data that
57        //   outlive `'de`. Therefore, `$name::Owned<'de>` also does not yield
58        //   any references to decoded data that outlive `'de`.
59        // - `$name` is `#[repr(transparent)]` over the transport `T`, and
60        //   `zero_padding` calls `T::zero_padding` on `transport`. `_protocol`
61        //   is a ZST which does not have any padding bytes to zero-initialize.
62        unsafe impl<P: 'static, T: Wire> Wire for $name<P, T> {
63            type Narrowed<'de> = $name<P, T::Narrowed<'de>>;
64
65            #[inline]
66            fn zero_padding(out: &mut MaybeUninit<Self>) {
67                munge!(let Self { transport, _protocol: _ } = out);
68                T::zero_padding(transport);
69            }
70        }
71
72        impl<P, T> $name<P, T> {
73            #[doc = concat!(
74                "Converts from `&",
75                stringify!($name),
76                "<P, T>` to `",
77                stringify!($name),
78                "<P, &T>`.",
79            )]
80            pub fn as_ref(&self) -> $name<P, &T> {
81                $name { transport: &self.transport, _protocol: PhantomData }
82            }
83
84            /// Returns a new endpoint over the given transport.
85            pub fn from_untyped(transport: T) -> Self {
86                Self { transport, _protocol: PhantomData }
87            }
88
89            /// Returns the underlying transport.
90            pub fn into_untyped(self) -> T {
91                self.transport
92            }
93
94            /// Returns the executor for the underlying transport.
95            pub fn executor(&self) -> T::Executor
96            where
97                T: HasExecutor,
98            {
99                self.transport.executor()
100            }
101        }
102
103        // SAFETY: `$name` is `#[repr(transparent)]` over the transport `T`, and `decode` calls
104        // `T::decode` on `transport`. `_protocol` is a ZST which does not have any data to decode.
105        unsafe impl<D, P, T> Decode<D> for $name<P, T>
106        where
107            D: ?Sized,
108            P: 'static,
109            T: Decode<D, Constraint=()>,
110        {
111            fn decode(slot: Slot<'_, Self>, decoder: &mut D, constraint:  Self::Constraint) -> Result<(), DecodeError> {
112                munge!(let Self { transport, _protocol: _ } = slot);
113                T::decode(transport, decoder, constraint)
114            }
115        }
116
117        // SAFETY: `$name` is `#[repr(transparent)]` over the transport `T`, and `encode` calls
118        // `T::encode` on `transport`. `_protocol` is a ZST which does not have any data to encode.
119        unsafe impl<W, E, P, T> Encode<$name<P, W>, E> for $name<P, T>
120        where
121            E: ?Sized,
122            P: 'static,
123            T: Encode<W, E>,
124            W: Wire<Constraint = ()>,
125        {
126            fn encode(
127                self,
128                encoder: &mut E,
129                out: &mut MaybeUninit<$name<P, W>>,
130                constraint:  (),
131            ) -> Result<(), EncodeError> {
132                munge!(let $name { transport, _protocol: _ } = out);
133                self.transport.encode(encoder, transport, constraint)
134            }
135        }
136
137        // SAFETY: `$name` is `#[repr(transparent)]` over the transport `T`, and `encode_ref` calls
138        // `T::encode_ref` on `transport`. `_protocol` is a ZST which does not have any data to
139        // encode.
140        unsafe impl<'a, W, E, P, T> Encode<$name<P, W>, E> for &'a $name<P, T>
141        where
142            E: ?Sized,
143            P: 'static,
144            &'a T: Encode<W, E>,
145            W: Wire<Constraint = ()>,
146        {
147            fn encode(
148                self,
149                encoder: &mut E,
150                out: &mut MaybeUninit<$name<P, W>>,
151                constraint:  (),
152            ) -> Result<(), EncodeError> {
153                self.as_ref().encode(encoder, out, constraint)
154            }
155        }
156
157        // SAFETY: `$name` is `#[repr(transparent)]` over the transport `T`, and `encode_option`
158        // calls `T::encode_option` on `transport`. `_protocol` is a ZST which does not have any
159        // data to encode.
160        unsafe impl<W, E, P, T> EncodeOption<$name<P, W>, E> for $name<P, T>
161        where
162            E: ?Sized,
163            P: 'static,
164            T: EncodeOption<W, E>,
165            W: Wire<Constraint = ()>
166        {
167            fn encode_option(
168                this: Option<Self>,
169                encoder: &mut E,
170                out: &mut MaybeUninit<$name<P, W>>,
171                constraint: (),
172            ) -> Result<(), EncodeError> {
173                munge!(let $name { transport, _protocol: _ } = out);
174                T::encode_option(this.map(|this| this.transport), encoder, transport, constraint)
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<'a, W, E, P, T> EncodeOption<$name<P, W>, E> for &'a $name<P, T>
182        where
183            E: ?Sized,
184            P: 'static,
185            &'a T: EncodeOption<W, E>,
186            W: Wire<Constraint = ()>
187        {
188            fn encode_option(
189                this: Option<Self>,
190                encoder: &mut E,
191                out: &mut MaybeUninit<$name<P, W>>,
192                constraint:  (),
193            ) -> Result<(), EncodeError> {
194                munge!(let $name { transport, _protocol: _ } = out);
195                <&T>::encode_option(this.map(|this| &this.transport), encoder, transport, constraint)
196            }
197        }
198
199        impl<P, T, U> FromWire<$name<P, U>> for $name<P, T>
200        where
201            T: FromWire<U>,
202        {
203            #[inline]
204            fn from_wire(wire: $name<P, U>) -> Self {
205                $name {
206                    transport: T::from_wire(wire.transport),
207                    _protocol: PhantomData,
208                }
209            }
210        }
211
212        impl<P, T: IntoNatural> IntoNatural for $name<P, T> {
213            type Natural = $name<P, T::Natural>;
214        }
215
216        impl<P, T, U> FromWireRef<$name<P, U>> for $name<P, T>
217        where
218            T: FromWireRef<U>,
219        {
220            #[inline]
221            fn from_wire_ref(wire: &$name<P, U>) -> Self {
222                $name {
223                    transport: T::from_wire_ref(&wire.transport),
224                    _protocol: PhantomData,
225                }
226            }
227        }
228
229        impl<P, T, U> FromWireOption<$name<P, U>> for $name<P, T>
230        where
231            P: 'static,
232            T: FromWireOption<U>,
233            U: Wire,
234        {
235            #[inline]
236            fn from_wire_option(wire: $name<P, U>) -> Option<Self> {
237                T::from_wire_option(wire.transport).map(|transport| $name {
238                    transport,
239                    _protocol: PhantomData,
240                })
241            }
242        }
243
244        impl<P, T, U> FromWireOptionRef<$name<P, U>> for $name<P, T>
245        where
246            P: 'static,
247            T: FromWireOptionRef<U>,
248            U: Wire,
249        {
250            #[inline]
251            fn from_wire_option_ref(wire: &$name<P, U>) -> Option<Self> {
252                T::from_wire_option_ref(&wire.transport).map(|transport| $name {
253                    transport,
254                    _protocol: PhantomData,
255                })
256            }
257        }
258    };
259}
260
261endpoint! {
262    /// The client end of a protocol.
263    ClientEnd
264}
265
266endpoint! {
267    /// The server end of a protocol.
268    ServerEnd
269}
270
271/// A client or server handler join handle.
272pub type HandlerJoinHandle<T, H, E = <T as HasExecutor>::Executor> =
273    <E as Executor>::JoinHandle<Result<H, ProtocolError<<T as Transport>::Error>>>;
274
275impl<P, T: Transport> ClientEnd<P, T> {
276    // -------------------------------------------------------------------------
277    // Non-local executor API
278    // -------------------------------------------------------------------------
279
280    /// Spawns a dispatcher for the given client end with a handler computed
281    /// from a closure on an executor.
282    ///
283    /// Returns the client and a join handle for the spawned task.
284    pub fn spawn_handler_full_on_with<H, E>(
285        self,
286        create_handler: impl FnOnce(Client<P, T>) -> H,
287        executor: &E,
288    ) -> (Client<P, T>, HandlerJoinHandle<T, H, E>)
289    where
290        P: DispatchClientMessage<H, T>,
291        T: 'static,
292        H: Send + 'static,
293        E: Executor,
294    {
295        let dispatcher = ClientDispatcher::new(self);
296        let client = dispatcher.client();
297        let handler = create_handler(client.clone());
298        (client, executor.spawn(dispatcher.run(handler)))
299    }
300
301    /// Spawns a dispatcher for the given client end with a handler on an
302    /// executor.
303    ///
304    /// Returns the client and a join handle for the spawned task.
305    pub fn spawn_handler_full_on<H, E>(
306        self,
307        handler: H,
308        executor: &E,
309    ) -> (Client<P, T>, HandlerJoinHandle<T, H, E>)
310    where
311        P: DispatchClientMessage<H, T>,
312        T: 'static,
313        H: Send + 'static,
314        E: Executor,
315    {
316        self.spawn_handler_full_on_with(|_| handler, executor)
317    }
318
319    /// Spawns a dispatcher for the given client end with a handler computed
320    /// from a closure on an executor.
321    ///
322    /// Returns the client.
323    pub fn spawn_handler_on_with<H, E>(
324        self,
325        create_handler: impl FnOnce(Client<P, T>) -> H,
326        executor: &E,
327    ) -> Client<P, T>
328    where
329        P: DispatchClientMessage<H, T>,
330        T: 'static,
331        H: Send + 'static,
332        E: Executor,
333    {
334        Self::spawn_handler_full_on_with(self, create_handler, executor).0
335    }
336
337    /// Spawns a dispatcher for the given client end with a handler on an
338    /// executor.
339    ///
340    /// Returns the client.
341    pub fn spawn_handler_on<H, E>(self, handler: H, executor: &E) -> Client<P, T>
342    where
343        P: DispatchClientMessage<H, T>,
344        T: 'static,
345        H: Send + 'static,
346        E: Executor,
347    {
348        self.spawn_handler_on_with(|_| handler, executor)
349    }
350
351    /// Spawns a dispatcher for the given client end with a handler computed
352    /// from a closure on the default executor for the transport.
353    ///
354    /// Returns the client and a join handle for the spawned task.
355    pub fn spawn_handler_full_with<H>(
356        self,
357        create_handler: impl FnOnce(Client<P, T>) -> H,
358    ) -> (Client<P, T>, HandlerJoinHandle<T, H>)
359    where
360        P: DispatchClientMessage<H, T>,
361        T: HasExecutor + 'static,
362        H: Send + 'static,
363    {
364        let executor = self.executor();
365        Self::spawn_handler_full_on_with(self, create_handler, &executor)
366    }
367
368    /// Spawns a dispatcher for the given client end with a handler on the
369    /// default executor for the transport.
370    ///
371    /// Returns the client and a join handle for the spawned task.
372    pub fn spawn_handler_full<H>(self, handler: H) -> (Client<P, T>, HandlerJoinHandle<T, H>)
373    where
374        P: DispatchClientMessage<H, T>,
375        T: HasExecutor + 'static,
376        H: Send + 'static,
377    {
378        self.spawn_handler_full_with(|_| handler)
379    }
380
381    /// Spawns a dispatcher for the given client end with a handler computed
382    /// from a closure on the default executor for the transport.
383    ///
384    /// Returns the client.
385    pub fn spawn_handler_with<H>(
386        self,
387        create_handler: impl FnOnce(Client<P, T>) -> H,
388    ) -> Client<P, T>
389    where
390        P: DispatchClientMessage<H, T>,
391        T: HasExecutor + 'static,
392        H: Send + 'static,
393    {
394        let executor = self.executor();
395        Self::spawn_handler_on_with(self, create_handler, &executor)
396    }
397
398    /// Spawns a dispatcher for the given client end with a handler on the
399    /// default executor for the transport.
400    ///
401    /// Returns the client.
402    pub fn spawn_handler<H>(self, handler: H) -> Client<P, T>
403    where
404        P: DispatchClientMessage<H, T>,
405        T: HasExecutor + 'static,
406        H: Send + 'static,
407    {
408        self.spawn_handler_with(|_| handler)
409    }
410
411    /// Spawns a dispatcher for the given client end on an executor.
412    ///
413    /// The spawned dispatcher will ignore all incoming events. Returns the
414    /// client and a join handle for the spawned task.
415    pub fn spawn_full_on<E>(self, executor: &E) -> (Client<P, T>, HandlerJoinHandle<T, (), E>)
416    where
417        P: DispatchClientMessage<IgnoreEvents, T>,
418        T: 'static,
419        E: Executor,
420    {
421        let dispatcher = ClientDispatcher::new(self);
422        let client = dispatcher.client();
423        (client, executor.spawn(dispatcher.run_client()))
424    }
425
426    /// Spawns a dispatcher for the given client end on an executor.
427    ///
428    /// The spawned dispatcher will ignore all incoming events. Returns the
429    /// client.
430    pub fn spawn_on<E>(self, executor: &E) -> Client<P, T>
431    where
432        P: DispatchClientMessage<IgnoreEvents, T>,
433        T: 'static,
434        E: Executor,
435    {
436        Self::spawn_full_on(self, executor).0
437    }
438
439    /// Spawns a dispatcher for the given client end on the default executor for
440    /// the transport.
441    ///
442    /// The spawned dispatcher will ignore all incoming events. Returns the
443    /// client and a join handle for the spawned task.
444    pub fn spawn_full(self) -> (Client<P, T>, HandlerJoinHandle<T, ()>)
445    where
446        P: DispatchClientMessage<IgnoreEvents, T>,
447        T: HasExecutor + 'static,
448    {
449        let executor = self.executor();
450        Self::spawn_full_on(self, &executor)
451    }
452
453    /// Spawns a dispatcher for the given client end on the default executor for
454    /// the transport.
455    ///
456    /// The spawned dispatcher will ignore all incoming events. Returns the
457    /// client.
458    pub fn spawn(self) -> Client<P, T>
459    where
460        P: DispatchClientMessage<IgnoreEvents, T>,
461        T: HasExecutor + 'static,
462    {
463        let executor = self.executor();
464        Self::spawn_on(self, &executor)
465    }
466
467    // -------------------------------------------------------------------------
468    // Non-local handler on local executor API
469    // -------------------------------------------------------------------------
470
471    /// Spawns a dispatcher for the given client end with a handler computed
472    /// from a closure on a local executor.
473    ///
474    /// Returns the client and a join handle for the spawned task.
475    pub fn spawn_as_local_handler_full_on_with<H, E>(
476        self,
477        create_handler: impl FnOnce(Client<P, T>) -> H,
478        executor: &E,
479    ) -> (Client<P, T>, HandlerJoinHandle<T, H, E>)
480    where
481        P: DispatchLocalClientMessage<Local<H>, T>,
482        T: 'static,
483        H: 'static,
484        E: LocalExecutor,
485    {
486        let dispatcher = ClientDispatcher::new(self);
487        let client = dispatcher.client();
488        let handler = create_handler(client.clone());
489        (
490            client,
491            executor.spawn_local(async {
492                dispatcher.run_local(Local(handler)).await.map(|local| local.0)
493            }),
494        )
495    }
496
497    /// Spawns a dispatcher for the given client end with a handler on a local
498    /// executor.
499    ///
500    /// Returns the client and a join handle for the spawned task.
501    pub fn spawn_as_local_handler_full_on<H, E>(
502        self,
503        handler: H,
504        executor: &E,
505    ) -> (Client<P, T>, HandlerJoinHandle<T, H, E>)
506    where
507        P: DispatchLocalClientMessage<Local<H>, T>,
508        T: 'static,
509        H: 'static,
510        E: LocalExecutor,
511    {
512        self.spawn_as_local_handler_full_on_with(|_| handler, executor)
513    }
514
515    /// Spawns a dispatcher for the given client end with a handler computed
516    /// from a closure on a local executor.
517    ///
518    /// Returns the client.
519    pub fn spawn_as_local_handler_on_with<H, E>(
520        self,
521        create_handler: impl FnOnce(Client<P, T>) -> H,
522        executor: &E,
523    ) -> Client<P, T>
524    where
525        P: DispatchLocalClientMessage<Local<H>, T>,
526        T: 'static,
527        H: 'static,
528        E: LocalExecutor,
529    {
530        Self::spawn_as_local_handler_full_on_with(self, create_handler, executor).0
531    }
532
533    /// Spawns a dispatcher for the given client end with a handler on a local
534    /// executor.
535    ///
536    /// Returns the client.
537    pub fn spawn_as_local_handler_on<H, E>(self, handler: H, executor: &E) -> Client<P, T>
538    where
539        P: DispatchLocalClientMessage<Local<H>, T>,
540        T: 'static,
541        H: 'static,
542        E: LocalExecutor,
543    {
544        self.spawn_as_local_handler_on_with(|_| handler, executor)
545    }
546
547    /// Spawns a dispatcher for the given client end with a handler computed
548    /// from a closure on the default executor for the transport.
549    ///
550    /// Returns the client and a join handle for the spawned task.
551    pub fn spawn_as_local_handler_full_with<H>(
552        self,
553        create_handler: impl FnOnce(Client<P, T>) -> H,
554    ) -> (Client<P, T>, HandlerJoinHandle<T, H>)
555    where
556        P: DispatchLocalClientMessage<Local<H>, T>,
557        T: HasExecutor + 'static,
558        T::Executor: LocalExecutor,
559        H: 'static,
560    {
561        let executor = self.executor();
562        Self::spawn_as_local_handler_full_on_with(self, create_handler, &executor)
563    }
564
565    /// Spawns a dispatcher for the given client end with a handler on the
566    /// default executor for the transport.
567    ///
568    /// Returns the client and a join handle for the spawned task.
569    pub fn spawn_as_local_handler_full<H>(
570        self,
571        handler: H,
572    ) -> (Client<P, T>, HandlerJoinHandle<T, H>)
573    where
574        P: DispatchLocalClientMessage<Local<H>, T>,
575        T: HasExecutor + 'static,
576        T::Executor: LocalExecutor,
577        H: 'static,
578    {
579        self.spawn_as_local_handler_full_with(|_| handler)
580    }
581
582    /// Spawns a dispatcher for the given client end with a handler computed
583    /// from a closure on the default executor for the transport.
584    ///
585    /// Returns the client.
586    pub fn spawn_as_local_handler_with<H>(
587        self,
588        create_handler: impl FnOnce(Client<P, T>) -> H,
589    ) -> Client<P, T>
590    where
591        P: DispatchLocalClientMessage<Local<H>, T>,
592        T: HasExecutor + 'static,
593        T::Executor: LocalExecutor,
594        H: 'static,
595    {
596        let executor = self.executor();
597        Self::spawn_as_local_handler_on_with(self, create_handler, &executor)
598    }
599
600    /// Spawns a dispatcher for the given client end with a handler on the
601    /// default executor for the transport.
602    ///
603    /// Returns the client.
604    pub fn spawn_as_local_handler<H>(self, handler: H) -> Client<P, T>
605    where
606        P: DispatchLocalClientMessage<Local<H>, T>,
607        T: HasExecutor + 'static,
608        T::Executor: LocalExecutor,
609        H: 'static,
610    {
611        self.spawn_as_local_handler_with(|_| handler)
612    }
613
614    // -------------------------------------------------------------------------
615    // Local executor API
616    // -------------------------------------------------------------------------
617
618    /// Spawns a dispatcher for the given client end with a handler computed
619    /// from a closure on a local executor.
620    ///
621    /// Returns the client and a join handle for the spawned task.
622    pub fn spawn_local_handler_full_on_with<H, E>(
623        self,
624        create_handler: impl FnOnce(Client<P, T>) -> H,
625        executor: &E,
626    ) -> (Client<P, T>, HandlerJoinHandle<T, H, E>)
627    where
628        P: DispatchLocalClientMessage<H, T>,
629        T: 'static,
630        H: 'static,
631        E: LocalExecutor,
632    {
633        let dispatcher = ClientDispatcher::new(self);
634        let client = dispatcher.client();
635        let handler = create_handler(client.clone());
636        (client, executor.spawn_local(dispatcher.run_local(handler)))
637    }
638
639    /// Spawns a dispatcher for the given client end with a handler on a local
640    /// executor.
641    ///
642    /// Returns the client and a join handle for the spawned task.
643    pub fn spawn_local_handler_full_on<H, E>(
644        self,
645        handler: H,
646        executor: &E,
647    ) -> (Client<P, T>, HandlerJoinHandle<T, H, E>)
648    where
649        P: DispatchLocalClientMessage<H, T>,
650        T: 'static,
651        H: 'static,
652        E: LocalExecutor,
653    {
654        self.spawn_local_handler_full_on_with(|_| handler, executor)
655    }
656
657    /// Spawns a dispatcher for the given client end with a handler computed
658    /// from a closure on a local executor.
659    ///
660    /// Returns the client.
661    pub fn spawn_local_handler_on_with<H, E>(
662        self,
663        create_handler: impl FnOnce(Client<P, T>) -> H,
664        executor: &E,
665    ) -> Client<P, T>
666    where
667        P: DispatchLocalClientMessage<H, T>,
668        T: 'static,
669        H: 'static,
670        E: LocalExecutor,
671    {
672        Self::spawn_local_handler_full_on_with(self, create_handler, executor).0
673    }
674
675    /// Spawns a dispatcher for the given client end with a handler on a local
676    /// executor.
677    ///
678    /// Returns the client.
679    pub fn spawn_local_handler_on<H, E>(self, handler: H, executor: &E) -> Client<P, T>
680    where
681        P: DispatchLocalClientMessage<H, T>,
682        T: 'static,
683        H: 'static,
684        E: LocalExecutor,
685    {
686        self.spawn_local_handler_on_with(|_| handler, executor)
687    }
688
689    /// Spawns a dispatcher for the given client end with a handler computed
690    /// from a closure on the default executor for the transport.
691    ///
692    /// Returns the client and a join handle for the spawned task.
693    pub fn spawn_local_handler_full_with<H>(
694        self,
695        create_handler: impl FnOnce(Client<P, T>) -> H,
696    ) -> (Client<P, T>, HandlerJoinHandle<T, H>)
697    where
698        P: DispatchLocalClientMessage<H, T>,
699        T: HasExecutor + 'static,
700        T::Executor: LocalExecutor,
701        H: 'static,
702    {
703        let executor = self.executor();
704        Self::spawn_local_handler_full_on_with(self, create_handler, &executor)
705    }
706
707    /// Spawns a dispatcher for the given client end with a handler on the
708    /// default executor for the transport.
709    ///
710    /// Returns the client and a join handle for the spawned task.
711    pub fn spawn_local_handler_full<H>(self, handler: H) -> (Client<P, T>, HandlerJoinHandle<T, H>)
712    where
713        P: DispatchLocalClientMessage<H, T>,
714        T: HasExecutor + 'static,
715        T::Executor: LocalExecutor,
716        H: 'static,
717    {
718        self.spawn_local_handler_full_with(|_| handler)
719    }
720
721    /// Spawns a dispatcher for the given client end with a handler computed
722    /// from a closure on the default executor for the transport.
723    ///
724    /// Returns the client.
725    pub fn spawn_local_handler_with<H>(
726        self,
727        create_handler: impl FnOnce(Client<P, T>) -> H,
728    ) -> Client<P, T>
729    where
730        P: DispatchLocalClientMessage<H, T>,
731        T: HasExecutor + 'static,
732        T::Executor: LocalExecutor,
733        H: 'static,
734    {
735        let executor = self.executor();
736        Self::spawn_local_handler_on_with(self, create_handler, &executor)
737    }
738
739    /// Spawns a dispatcher for the given client end with a handler on the
740    /// default executor for the transport.
741    ///
742    /// Returns the client.
743    pub fn spawn_local_handler<H>(self, handler: H) -> Client<P, T>
744    where
745        P: DispatchLocalClientMessage<H, T>,
746        T: HasExecutor + 'static,
747        T::Executor: LocalExecutor,
748        H: 'static,
749    {
750        self.spawn_local_handler_with(|_| handler)
751    }
752}
753
754impl<P, T: Transport> ServerEnd<P, T> {
755    // -------------------------------------------------------------------------
756    // Non-local executor API
757    // -------------------------------------------------------------------------
758
759    /// Spawns a dispatcher for the given server end with a handler computed
760    /// from a closure on an executor.
761    ///
762    /// Returns the join handle for the spawned task and the server.
763    pub fn spawn_full_on_with<H, E>(
764        self,
765        create_handler: impl FnOnce(Server<P, T>) -> H,
766        executor: &E,
767    ) -> (HandlerJoinHandle<T, H, E>, Server<P, T>)
768    where
769        P: DispatchServerMessage<H, T>,
770        T: 'static,
771        H: Send + 'static,
772        E: Executor,
773    {
774        let dispatcher = ServerDispatcher::new(self);
775        let server = dispatcher.server();
776        let handler = create_handler(server.clone());
777        (executor.spawn(dispatcher.run(handler)), server)
778    }
779
780    /// Spawns a dispatcher for the given server end with a handler on an
781    /// executor.
782    ///
783    /// Returns the join handle for the spawned task and the server.
784    pub fn spawn_full_on<H, E>(
785        self,
786        handler: H,
787        executor: &E,
788    ) -> (HandlerJoinHandle<T, H, E>, Server<P, T>)
789    where
790        P: DispatchServerMessage<H, T>,
791        T: 'static,
792        H: Send + 'static,
793        E: Executor,
794    {
795        self.spawn_full_on_with(|_| handler, executor)
796    }
797
798    /// Spawns a dispatcher for the given server end with a handler computed
799    /// from a closure on an executor.
800    ///
801    /// Returns the join handle for the spawned task.
802    pub fn spawn_on_with<H, E>(
803        self,
804        create_handler: impl FnOnce(Server<P, T>) -> H,
805        executor: &E,
806    ) -> HandlerJoinHandle<T, H, E>
807    where
808        P: DispatchServerMessage<H, T>,
809        T: 'static,
810        H: Send + 'static,
811        E: Executor,
812    {
813        let dispatcher = ServerDispatcher::new(self);
814        let handler = create_handler(dispatcher.server());
815        executor.spawn(dispatcher.run(handler))
816    }
817
818    /// Spawns a dispatcher for the given server end with a handler on an
819    /// executor.
820    ///
821    /// Returns the join handle for the spawned task.
822    pub fn spawn_on<H, E>(self, handler: H, executor: &E) -> HandlerJoinHandle<T, H, E>
823    where
824        P: DispatchServerMessage<H, T>,
825        T: 'static,
826        H: Send + 'static,
827        E: Executor,
828    {
829        self.spawn_on_with(|_| handler, executor)
830    }
831
832    /// Spawns a dispatcher for the given server end with a handler computed
833    /// from a closure on the default executor for the transport.
834    ///
835    /// Returns the join handle for the spawned task and the server.
836    pub fn spawn_full_with<H>(
837        self,
838        create_handler: impl FnOnce(Server<P, T>) -> H,
839    ) -> (HandlerJoinHandle<T, H>, Server<P, T>)
840    where
841        P: DispatchServerMessage<H, T>,
842        T: HasExecutor + 'static,
843        H: Send + 'static,
844    {
845        let executor = self.executor();
846        Self::spawn_full_on_with(self, create_handler, &executor)
847    }
848
849    /// Spawns a dispatcher for the given server end with a handler on the
850    /// default executor for the transport.
851    ///
852    /// Returns the join handle for the spawned task and the server.
853    pub fn spawn_full<H>(self, handler: H) -> (HandlerJoinHandle<T, H>, Server<P, T>)
854    where
855        P: DispatchServerMessage<H, T>,
856        T: HasExecutor + 'static,
857        H: Send + 'static,
858    {
859        self.spawn_full_with(|_| handler)
860    }
861
862    /// Spawns a dispatcher for the given server end with a handler computed
863    /// from a closure on the default executor for the transport.
864    ///
865    /// Returns the join handle for the spawned task.
866    pub fn spawn_with<H>(
867        self,
868        create_handler: impl FnOnce(Server<P, T>) -> H,
869    ) -> HandlerJoinHandle<T, H>
870    where
871        P: DispatchServerMessage<H, T>,
872        T: HasExecutor + 'static,
873        H: Send + 'static,
874    {
875        let executor = self.executor();
876        Self::spawn_on_with(self, create_handler, &executor)
877    }
878
879    /// Spawns a dispatcher for the given server end with a handler on the
880    /// default executor for the transport.
881    ///
882    /// Returns the join handle for the spawned task.
883    pub fn spawn<H>(self, handler: H) -> HandlerJoinHandle<T, H>
884    where
885        P: DispatchServerMessage<H, T>,
886        T: HasExecutor + 'static,
887        H: Send + 'static,
888    {
889        self.spawn_with(|_| handler)
890    }
891
892    // -------------------------------------------------------------------------
893    // Local executor API
894    // -------------------------------------------------------------------------
895
896    /// Spawns a dispatcher for the given server end with a handler computed
897    /// from a closure on a local executor.
898    ///
899    /// Returns the join handle for the spawned task and the server.
900    pub fn spawn_as_local_full_on_with<H, E>(
901        self,
902        create_handler: impl FnOnce(Server<P, T>) -> H,
903        executor: &E,
904    ) -> (HandlerJoinHandle<T, H, E>, Server<P, T>)
905    where
906        P: DispatchLocalServerMessage<Local<H>, T>,
907        T: 'static,
908        H: 'static,
909        E: LocalExecutor,
910    {
911        let dispatcher = ServerDispatcher::new(self);
912        let server = dispatcher.server();
913        let handler = create_handler(server.clone());
914        (
915            executor.spawn_local(async {
916                dispatcher.run_local(Local(handler)).await.map(|local| local.0)
917            }),
918            server,
919        )
920    }
921
922    /// Spawns a dispatcher for the given server end with a handler on a local
923    /// executor.
924    ///
925    /// Returns the join handle for the spawned task and the server.
926    pub fn spawn_as_local_full_on<H, E>(
927        self,
928        handler: H,
929        executor: &E,
930    ) -> (HandlerJoinHandle<T, H, E>, Server<P, T>)
931    where
932        P: DispatchLocalServerMessage<Local<H>, T>,
933        T: 'static,
934        H: 'static,
935        E: LocalExecutor,
936    {
937        self.spawn_as_local_full_on_with(|_| handler, executor)
938    }
939
940    /// Spawns a dispatcher for the given server end with a handler computed
941    /// from a closure on a local executor.
942    ///
943    /// Returns the join handle for the spawned task.
944    pub fn spawn_as_local_on_with<H, E>(
945        self,
946        create_handler: impl FnOnce(Server<P, T>) -> H,
947        executor: &E,
948    ) -> HandlerJoinHandle<T, H, E>
949    where
950        P: DispatchLocalServerMessage<Local<H>, T>,
951        T: 'static,
952        H: 'static,
953        E: LocalExecutor,
954    {
955        let dispatcher = ServerDispatcher::new(self);
956        let handler = create_handler(dispatcher.server());
957        executor
958            .spawn_local(async { dispatcher.run_local(Local(handler)).await.map(|local| local.0) })
959    }
960
961    /// Spawns a dispatcher for the given server end with a handler on a local
962    /// executor.
963    ///
964    /// Returns the join handle for the spawned task.
965    pub fn spawn_as_local_on<H, E>(self, handler: H, executor: &E) -> HandlerJoinHandle<T, H, E>
966    where
967        P: DispatchLocalServerMessage<Local<H>, T>,
968        T: 'static,
969        H: 'static,
970        E: LocalExecutor,
971    {
972        self.spawn_as_local_on_with(|_| handler, executor)
973    }
974
975    /// Spawns a dispatcher for the given server end with a handler computed
976    /// from a closure on the default executor for the transport.
977    ///
978    /// Returns the join handle for the spawned task and the server.
979    pub fn spawn_as_local_full_with<H>(
980        self,
981        create_handler: impl FnOnce(Server<P, T>) -> H,
982    ) -> (HandlerJoinHandle<T, H>, Server<P, T>)
983    where
984        P: DispatchLocalServerMessage<Local<H>, T>,
985        T: HasExecutor + 'static,
986        T::Executor: LocalExecutor,
987        H: 'static,
988    {
989        let executor = self.executor();
990        Self::spawn_as_local_full_on_with(self, create_handler, &executor)
991    }
992
993    /// Spawns a dispatcher for the given server end with a handler on the
994    /// default executor for the transport.
995    ///
996    /// Returns the join handle for the spawned task and the server.
997    pub fn spawn_as_local_full<H>(self, handler: H) -> (HandlerJoinHandle<T, H>, Server<P, T>)
998    where
999        P: DispatchLocalServerMessage<Local<H>, T>,
1000        T: HasExecutor + 'static,
1001        T::Executor: LocalExecutor,
1002        H: 'static,
1003    {
1004        self.spawn_as_local_full_with(|_| handler)
1005    }
1006
1007    /// Spawns a dispatcher for the given server end with a handler computed
1008    /// from a closure on the default executor for the transport.
1009    ///
1010    /// Returns the join handle for the spawned task.
1011    pub fn spawn_as_local_with<H>(
1012        self,
1013        create_handler: impl FnOnce(Server<P, T>) -> H,
1014    ) -> HandlerJoinHandle<T, H>
1015    where
1016        P: DispatchLocalServerMessage<Local<H>, T>,
1017        T: HasExecutor + 'static,
1018        T::Executor: LocalExecutor,
1019        H: 'static,
1020    {
1021        let executor = self.executor();
1022        Self::spawn_as_local_on_with(self, create_handler, &executor)
1023    }
1024
1025    /// Spawns a dispatcher for the given server end with a handler on the
1026    /// default executor for the transport.
1027    ///
1028    /// Returns the join handle for the spawned task.
1029    pub fn spawn_as_local<H>(self, handler: H) -> HandlerJoinHandle<T, H>
1030    where
1031        P: DispatchLocalServerMessage<Local<H>, T>,
1032        T: HasExecutor + 'static,
1033        T::Executor: LocalExecutor,
1034        H: 'static,
1035    {
1036        self.spawn_as_local_with(|_| handler)
1037    }
1038
1039    // -------------------------------------------------------------------------
1040    // Local executor API
1041    // -------------------------------------------------------------------------
1042
1043    /// Spawns a dispatcher for the given server end with a handler computed
1044    /// from a closure on a local executor.
1045    ///
1046    /// Returns the join handle for the spawned task and the server.
1047    pub fn spawn_local_full_on_with<H, E>(
1048        self,
1049        create_handler: impl FnOnce(Server<P, T>) -> H,
1050        executor: &E,
1051    ) -> (HandlerJoinHandle<T, H, E>, Server<P, T>)
1052    where
1053        P: DispatchLocalServerMessage<H, T>,
1054        T: 'static,
1055        H: 'static,
1056        E: LocalExecutor,
1057    {
1058        let dispatcher = ServerDispatcher::new(self);
1059        let server = dispatcher.server();
1060        let handler = create_handler(server.clone());
1061        (executor.spawn_local(dispatcher.run_local(handler)), server)
1062    }
1063
1064    /// Spawns a dispatcher for the given server end with a handler on a local
1065    /// executor.
1066    ///
1067    /// Returns the join handle for the spawned task and the server.
1068    pub fn spawn_local_full_on<H, E>(
1069        self,
1070        handler: H,
1071        executor: &E,
1072    ) -> (HandlerJoinHandle<T, H, E>, Server<P, T>)
1073    where
1074        P: DispatchLocalServerMessage<H, T>,
1075        T: 'static,
1076        H: 'static,
1077        E: LocalExecutor,
1078    {
1079        self.spawn_local_full_on_with(|_| handler, executor)
1080    }
1081
1082    /// Spawns a dispatcher for the given server end with a handler computed
1083    /// from a closure on a local executor.
1084    ///
1085    /// Returns the join handle for the spawned task.
1086    pub fn spawn_local_on_with<H, E>(
1087        self,
1088        create_handler: impl FnOnce(Server<P, T>) -> H,
1089        executor: &E,
1090    ) -> HandlerJoinHandle<T, H, E>
1091    where
1092        P: DispatchLocalServerMessage<H, T>,
1093        T: 'static,
1094        H: 'static,
1095        E: LocalExecutor,
1096    {
1097        let dispatcher = ServerDispatcher::new(self);
1098        let handler = create_handler(dispatcher.server());
1099        executor.spawn_local(dispatcher.run_local(handler))
1100    }
1101
1102    /// Spawns a dispatcher for the given server end with a handler on a local
1103    /// executor.
1104    ///
1105    /// Returns the join handle for the spawned task.
1106    pub fn spawn_local_on<H, E>(self, handler: H, executor: &E) -> HandlerJoinHandle<T, H, E>
1107    where
1108        P: DispatchLocalServerMessage<H, T>,
1109        T: 'static,
1110        H: 'static,
1111        E: LocalExecutor,
1112    {
1113        self.spawn_local_on_with(|_| handler, executor)
1114    }
1115
1116    /// Spawns a dispatcher for the given server end with a handler computed
1117    /// from a closure on the default executor for the transport.
1118    ///
1119    /// Returns the join handle for the spawned task and the server.
1120    pub fn spawn_local_full_with<H>(
1121        self,
1122        create_handler: impl FnOnce(Server<P, T>) -> H,
1123    ) -> (HandlerJoinHandle<T, H>, Server<P, T>)
1124    where
1125        P: DispatchLocalServerMessage<H, T>,
1126        T: HasExecutor + 'static,
1127        T::Executor: LocalExecutor,
1128        H: 'static,
1129    {
1130        let executor = self.executor();
1131        Self::spawn_local_full_on_with(self, create_handler, &executor)
1132    }
1133
1134    /// Spawns a dispatcher for the given server end with a handler on the
1135    /// default executor for the transport.
1136    ///
1137    /// Returns the join handle for the spawned task and the server.
1138    pub fn spawn_local_full<H>(self, handler: H) -> (HandlerJoinHandle<T, H>, Server<P, T>)
1139    where
1140        P: DispatchLocalServerMessage<H, T>,
1141        T: HasExecutor + 'static,
1142        T::Executor: LocalExecutor,
1143        H: 'static,
1144    {
1145        self.spawn_local_full_with(|_| handler)
1146    }
1147
1148    /// Spawns a dispatcher for the given server end with a handler computed
1149    /// from a closure on the default executor for the transport.
1150    ///
1151    /// Returns the join handle for the spawned task.
1152    pub fn spawn_local_with<H>(
1153        self,
1154        create_handler: impl FnOnce(Server<P, T>) -> H,
1155    ) -> HandlerJoinHandle<T, H>
1156    where
1157        P: DispatchLocalServerMessage<H, T>,
1158        T: HasExecutor + 'static,
1159        T::Executor: LocalExecutor,
1160        H: 'static,
1161    {
1162        let executor = self.executor();
1163        Self::spawn_local_on_with(self, create_handler, &executor)
1164    }
1165
1166    /// Spawns a dispatcher for the given server end with a handler on the
1167    /// default executor for the transport.
1168    ///
1169    /// Returns the join handle for the spawned task.
1170    pub fn spawn_local<H>(self, handler: H) -> HandlerJoinHandle<T, H>
1171    where
1172        P: DispatchLocalServerMessage<H, T>,
1173        T: HasExecutor + 'static,
1174        T::Executor: LocalExecutor,
1175        H: 'static,
1176    {
1177        self.spawn_local_with(|_| handler)
1178    }
1179}