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, Encodable, EncodableOption, Encode, EncodeError,
11    EncodeOption, EncodeOptionRef, EncodeRef, FromWire, FromWireOption, FromWireOptionRef,
12    FromWireRef, IntoNatural, Slot, Unconstrained, Wire, munge,
13};
14use fidl_next_protocol::{ProtocolError, Transport};
15
16use crate::{
17    Client, ClientDispatcher, DispatchClientMessage, DispatchServerMessage, Executor, HasExecutor,
18    HasTransport, IgnoreEvents, 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            T = <P as HasTransport>::Transport,
32        > {
33            transport: T,
34            _protocol: PhantomData<P>,
35        }
36
37        unsafe impl<P, T: Send> Send for $name<P, T> {}
38
39        unsafe impl<P, T: Sync> Sync for $name<P, T> {}
40
41        // SAFETY:
42        // - `$name::Decoded<'de>` wraps a `T::Decoded<'de>`. Because `T: Wire`, `T::Decoded<'de>`
43        //   does not yield any references to decoded data that outlive `'de`. Therefore,
44        //   `$name::Decoded<'de>` also does not yield any references to decoded data that outlive
45        //   `'de`.
46        // - `$name` is `#[repr(transparent)]` over the transport `T`, and `zero_padding` calls
47        //   `T::zero_padding` on `transport`. `_protocol` is a ZST which does not have any padding
48        //   bytes to zero-initialize.
49        unsafe impl<P: 'static, T: Wire> Wire for $name<P, T> {
50            type Decoded<'de> = $name<P, T::Decoded<'de>>;
51
52            #[inline]
53            fn zero_padding(out: &mut MaybeUninit<Self>) {
54                munge!(let Self { transport, _protocol: _ } = out);
55                T::zero_padding(transport);
56            }
57        }
58
59        impl<P, T> $name<P, T> {
60            #[doc = concat!(
61                "Converts from `&",
62                stringify!($name),
63                "<P, T>` to `",
64                stringify!($name),
65                "<P, &T>`.",
66            )]
67            pub fn as_ref(&self) -> $name<P, &T> {
68                $name { transport: &self.transport, _protocol: PhantomData }
69            }
70
71            /// Returns a new endpoint over the given transport.
72            pub fn from_untyped(transport: T) -> Self {
73                Self { transport, _protocol: PhantomData }
74            }
75
76            /// Returns the underlying transport.
77            pub fn into_untyped(self) -> T {
78                self.transport
79            }
80
81            /// Returns the executor for the underlying transport.
82            pub fn executor(&self) -> T::Executor
83            where
84                T: HasExecutor,
85            {
86                self.transport.executor()
87            }
88        }
89
90        // SAFETY: `$name` is `#[repr(transparent)]` over the transport `T`, and `decode` calls
91        // `T::decode` on `transport`. `_protocol` is a ZST which does not have any data to decode.
92        unsafe impl<D, P, T> Decode<D> for $name<P, T>
93        where
94            D: ?Sized,
95            P: 'static,
96            T: Decode<D>,
97            T: Constrained<Constraint=()>,
98        {
99            fn decode(slot: Slot<'_, Self>, decoder: &mut D, constraint:  <Self as Constrained>::Constraint) -> Result<(), DecodeError> {
100                munge!(let Self { transport, _protocol: _ } = slot);
101                T::decode(transport, decoder, constraint)
102            }
103        }
104
105        impl<P, T> Encodable for $name<P, T>
106        where
107            T: Encodable,
108            T::Encoded : Constrained<Constraint=()>,
109            P: 'static,
110        {
111            type Encoded = $name<P, T::Encoded>;
112        }
113
114        impl<P, T> EncodableOption for $name<P, T>
115        where
116            T: EncodableOption,
117            T::EncodedOption: Constrained<Constraint=()>,
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            T::Encoded: Constrained<Constraint=()>
131        {
132            fn encode(
133                self,
134                encoder: &mut E,
135                out: &mut MaybeUninit<Self::Encoded>,
136                constraint:  (),
137            ) -> Result<(), EncodeError> {
138                munge!(let Self::Encoded { transport, _protocol: _ } = out);
139                self.transport.encode(encoder, transport, constraint)
140            }
141        }
142
143        // SAFETY: `$name` is `#[repr(transparent)]` over the transport `T`, and `encode_ref` calls
144        // `T::encode_ref` on `transport`. `_protocol` is a ZST which does not have any data to
145        // encode.
146        unsafe impl<E, P, T> EncodeRef<E> for $name<P, T>
147        where
148            E: ?Sized,
149            P: 'static,
150            T: EncodeRef<E>,
151            T::Encoded: Constrained<Constraint=()>
152        {
153            fn encode_ref(
154                &self,
155                encoder: &mut E,
156                out: &mut MaybeUninit<Self::Encoded>,
157                constraint:  (),
158            ) -> Result<(), EncodeError> {
159                self.as_ref().encode(encoder, out, constraint)
160            }
161        }
162
163        // SAFETY: `$name` is `#[repr(transparent)]` over the transport `T`, and `encode_option`
164        // calls `T::encode_option` on `transport`. `_protocol` is a ZST which does not have any
165        // data to encode.
166        unsafe impl<E, P, T> EncodeOption<E> for $name<P, T>
167        where
168            E: ?Sized,
169            P: 'static,
170            T: EncodeOption<E>,
171            T::EncodedOption: Constrained<Constraint=()>
172        {
173            fn encode_option(
174                this: Option<Self>,
175                encoder: &mut E,
176                out: &mut MaybeUninit<Self::EncodedOption>,
177                constraint: (),
178            ) -> Result<(), EncodeError> {
179                munge!(let Self::EncodedOption { transport, _protocol: _ } = out);
180                T::encode_option(this.map(|this| this.transport), encoder, transport, constraint)
181            }
182        }
183
184        // SAFETY: `$name` is `#[repr(transparent)]` over the transport `T`, and `encode_option_ref`
185        // calls `T::encode_option_ref` on `transport`. `_protocol` is a ZST which does not have any
186        // data to encode.
187        unsafe impl<E, P, T> EncodeOptionRef<E> for $name<P, T>
188        where
189            E: ?Sized,
190            P: 'static,
191            T: EncodeOptionRef<E>,
192            T::EncodedOption: Constrained<Constraint=()>
193        {
194            fn encode_option_ref(
195                this: Option<&Self>,
196                encoder: &mut E,
197                out: &mut MaybeUninit<Self::EncodedOption>,
198                constraint:  (),
199            ) -> Result<(), EncodeError> {
200                munge!(let Self::EncodedOption { transport, _protocol: _ } = out);
201                T::encode_option_ref(this.map(|this| &this.transport), encoder, transport, constraint)
202            }
203        }
204
205        impl<P, T : Constrained<Constraint=()>> Unconstrained for $name<P, T> {}
206
207        impl<P, T, U> FromWire<$name<P, U>> for $name<P, T>
208        where
209            T: FromWire<U>,
210        {
211            #[inline]
212            fn from_wire(wire: $name<P, U>) -> Self {
213                $name {
214                    transport: T::from_wire(wire.transport),
215                    _protocol: PhantomData,
216                }
217            }
218        }
219
220        impl<P, T: IntoNatural> IntoNatural for $name<P, T> {
221            type Natural = $name<P, T::Natural>;
222        }
223
224        impl<P, T, U> FromWireRef<$name<P, U>> for $name<P, T>
225        where
226            T: FromWireRef<U>,
227        {
228            #[inline]
229            fn from_wire_ref(wire: &$name<P, U>) -> Self {
230                $name {
231                    transport: T::from_wire_ref(&wire.transport),
232                    _protocol: PhantomData,
233                }
234            }
235        }
236
237        impl<P, T, U> FromWireOption<$name<P, U>> for $name<P, T>
238        where
239            P: 'static,
240            T: FromWireOption<U>,
241            U: Wire,
242        {
243            #[inline]
244            fn from_wire_option(wire: $name<P, U>) -> Option<Self> {
245                T::from_wire_option(wire.transport).map(|transport| $name {
246                    transport,
247                    _protocol: PhantomData,
248                })
249            }
250        }
251
252        impl<P, T, U> FromWireOptionRef<$name<P, U>> for $name<P, T>
253        where
254            P: 'static,
255            T: FromWireOptionRef<U>,
256            U: Wire,
257        {
258            #[inline]
259            fn from_wire_option_ref(wire: &$name<P, U>) -> Option<Self> {
260                T::from_wire_option_ref(&wire.transport).map(|transport| $name {
261                    transport,
262                    _protocol: PhantomData,
263                })
264            }
265        }
266    };
267}
268
269endpoint! {
270    /// The client end of a protocol.
271    ClientEnd
272}
273
274endpoint! {
275    /// The server end of a protocol.
276    ServerEnd
277}
278
279/// A client or server handler task.
280pub type HandlerTask<T, H, E = <T as HasExecutor>::Executor> =
281    <E as Executor>::Task<Result<H, ProtocolError<<T as Transport>::Error>>>;
282
283impl<P, T: Transport> ClientEnd<P, T> {
284    /// Spawns a dispatcher for the given client end with a handler computed
285    /// from a closure on an executor.
286    ///
287    /// Returns the client and a join handle for the spawned task.
288    pub fn spawn_handler_full_on_with<H, E>(
289        self,
290        create_handler: impl FnOnce(Client<P, T>) -> H,
291        executor: &E,
292    ) -> (Client<P, T>, HandlerTask<T, H, E>)
293    where
294        P: DispatchClientMessage<H, T>,
295        T: 'static,
296        H: Send + 'static,
297        E: Executor,
298    {
299        let dispatcher = ClientDispatcher::new(self);
300        let client = dispatcher.client();
301        let handler = create_handler(client.clone());
302        (client, executor.spawn(dispatcher.run(handler)))
303    }
304
305    /// Spawns a dispatcher for the given client end with a handler on an
306    /// executor.
307    ///
308    /// Returns the client and a join handle for the spawned task.
309    pub fn spawn_handler_full_on<H, E>(
310        self,
311        handler: H,
312        executor: &E,
313    ) -> (Client<P, T>, HandlerTask<T, H, E>)
314    where
315        P: DispatchClientMessage<H, T>,
316        T: 'static,
317        H: Send + 'static,
318        E: Executor,
319    {
320        self.spawn_handler_full_on_with(|_| handler, executor)
321    }
322
323    /// Spawns a dispatcher for the given client end with a handler computed
324    /// from a closure on an executor.
325    ///
326    /// Returns the client.
327    pub fn spawn_handler_on_with<H, E>(
328        self,
329        create_handler: impl FnOnce(Client<P, T>) -> H,
330        executor: &E,
331    ) -> Client<P, T>
332    where
333        P: DispatchClientMessage<H, T>,
334        T: 'static,
335        H: Send + 'static,
336        E: Executor,
337    {
338        let (client, task) = Self::spawn_handler_full_on_with(self, create_handler, executor);
339        executor.detach(task);
340        client
341    }
342
343    /// Spawns a dispatcher for the given client end with a handler on an
344    /// executor.
345    ///
346    /// Returns the client.
347    pub fn spawn_handler_on<H, E>(self, handler: H, executor: &E) -> Client<P, T>
348    where
349        P: DispatchClientMessage<H, T>,
350        T: 'static,
351        H: Send + 'static,
352        E: Executor,
353    {
354        self.spawn_handler_on_with(|_| handler, executor)
355    }
356
357    /// Spawns a dispatcher for the given client end with a handler computed
358    /// from a closure on the default executor for the transport.
359    ///
360    /// Returns the client and a join handle for the spawned task.
361    pub fn spawn_handler_full_with<H>(
362        self,
363        create_handler: impl FnOnce(Client<P, T>) -> H,
364    ) -> (Client<P, T>, HandlerTask<T, H>)
365    where
366        P: DispatchClientMessage<H, T>,
367        T: HasExecutor + 'static,
368        H: Send + 'static,
369    {
370        let executor = self.executor();
371        Self::spawn_handler_full_on_with(self, create_handler, &executor)
372    }
373
374    /// Spawns a dispatcher for the given client end with a handler on the
375    /// default executor for the transport.
376    ///
377    /// Returns the client and a join handle for the spawned task.
378    pub fn spawn_handler_full<H>(self, handler: H) -> (Client<P, T>, HandlerTask<T, H>)
379    where
380        P: DispatchClientMessage<H, T>,
381        T: HasExecutor + 'static,
382        H: Send + 'static,
383    {
384        self.spawn_handler_full_with(|_| handler)
385    }
386
387    /// Spawns a dispatcher for the given client end with a handler computed
388    /// from a closure on the default executor for the transport.
389    ///
390    /// Returns the client.
391    pub fn spawn_handler_with<H>(
392        self,
393        create_handler: impl FnOnce(Client<P, T>) -> H,
394    ) -> Client<P, T>
395    where
396        P: DispatchClientMessage<H, T>,
397        T: HasExecutor + 'static,
398        H: Send + 'static,
399    {
400        let executor = self.executor();
401        Self::spawn_handler_on_with(self, create_handler, &executor)
402    }
403
404    /// Spawns a dispatcher for the given client end with a handler on the
405    /// default executor for the transport.
406    ///
407    /// Returns the client.
408    pub fn spawn_handler<H>(self, handler: H) -> Client<P, T>
409    where
410        P: DispatchClientMessage<H, T>,
411        T: HasExecutor + 'static,
412        H: Send + 'static,
413    {
414        self.spawn_handler_with(|_| handler)
415    }
416
417    /// Spawns a dispatcher for the given client end on an executor.
418    ///
419    /// The spawned dispatcher will ignore all incoming events. Returns the
420    /// client and a join handle for the spawned task.
421    pub fn spawn_full_on<E>(self, executor: &E) -> (Client<P, T>, HandlerTask<T, (), E>)
422    where
423        P: DispatchClientMessage<IgnoreEvents, T>,
424        T: 'static,
425        E: Executor,
426    {
427        let dispatcher = ClientDispatcher::new(self);
428        let client = dispatcher.client();
429        (client, executor.spawn(dispatcher.run_client()))
430    }
431
432    /// Spawns a dispatcher for the given client end on an executor.
433    ///
434    /// The spawned dispatcher will ignore all incoming events. Returns the
435    /// client.
436    pub fn spawn_on<E>(self, executor: &E) -> Client<P, T>
437    where
438        P: DispatchClientMessage<IgnoreEvents, T>,
439        T: 'static,
440        E: Executor,
441    {
442        let (client, task) = Self::spawn_full_on(self, executor);
443        executor.detach(task);
444        client
445    }
446
447    /// Spawns a dispatcher for the given client end on the default executor for
448    /// the transport.
449    ///
450    /// The spawned dispatcher will ignore all incoming events. Returns the
451    /// client and a join handle for the spawned task.
452    pub fn spawn_full(self) -> (Client<P, T>, HandlerTask<T, ()>)
453    where
454        P: DispatchClientMessage<IgnoreEvents, T>,
455        T: HasExecutor + 'static,
456    {
457        let executor = self.executor();
458        Self::spawn_full_on(self, &executor)
459    }
460
461    /// Spawns a dispatcher for the given client end on the default executor for
462    /// the transport.
463    ///
464    /// The spawned dispatcher will ignore all incoming events. Returns the
465    /// client.
466    pub fn spawn(self) -> Client<P, T>
467    where
468        P: DispatchClientMessage<IgnoreEvents, T>,
469        T: HasExecutor + 'static,
470    {
471        let executor = self.executor();
472        Self::spawn_on(self, &executor)
473    }
474}
475
476impl<P, T: Transport> ServerEnd<P, T> {
477    /// Spawns a dispatcher for the given server end with a handler computed
478    /// from a closure on an executor.
479    ///
480    /// Returns the join handle for the spawned task and the server.
481    pub fn spawn_full_on_with<H, E>(
482        self,
483        create_handler: impl FnOnce(Server<P, T>) -> H,
484        executor: &E,
485    ) -> (HandlerTask<T, H, E>, Server<P, T>)
486    where
487        P: DispatchServerMessage<H, T>,
488        T: 'static,
489        H: Send + 'static,
490        E: Executor,
491    {
492        let dispatcher = ServerDispatcher::new(self);
493        let server = dispatcher.server();
494        let handler = create_handler(server.clone());
495        (executor.spawn(dispatcher.run(handler)), server)
496    }
497
498    /// Spawns a dispatcher for the given server end with a handler on an
499    /// executor.
500    ///
501    /// Returns the join handle for the spawned task and the server.
502    pub fn spawn_full_on<H, E>(
503        self,
504        handler: H,
505        executor: &E,
506    ) -> (HandlerTask<T, H, E>, Server<P, T>)
507    where
508        P: DispatchServerMessage<H, T>,
509        T: 'static,
510        H: Send + 'static,
511        E: Executor,
512    {
513        self.spawn_full_on_with(|_| handler, executor)
514    }
515
516    /// Spawns a dispatcher for the given server end with a handler computed
517    /// from a closure on an executor.
518    ///
519    /// Returns the join handle for the spawned task.
520    pub fn spawn_on_with<H, E>(
521        self,
522        create_handler: impl FnOnce(Server<P, T>) -> H,
523        executor: &E,
524    ) -> HandlerTask<T, H, E>
525    where
526        P: DispatchServerMessage<H, T>,
527        T: 'static,
528        H: Send + 'static,
529        E: Executor,
530    {
531        let dispatcher = ServerDispatcher::new(self);
532        let handler = create_handler(dispatcher.server());
533        executor.spawn(dispatcher.run(handler))
534    }
535
536    /// Spawns a dispatcher for the given server end with a handler on an
537    /// executor.
538    ///
539    /// Returns the join handle for the spawned task.
540    pub fn spawn_on<H, E>(self, handler: H, executor: &E) -> HandlerTask<T, H, E>
541    where
542        P: DispatchServerMessage<H, T>,
543        T: 'static,
544        H: Send + 'static,
545        E: Executor,
546    {
547        self.spawn_on_with(|_| handler, executor)
548    }
549
550    /// Spawns a dispatcher for the given server end with a handler computed
551    /// from a closure on the default executor for the transport.
552    ///
553    /// Returns the join handle for the spawned task and the server.
554    pub fn spawn_full_with<H>(
555        self,
556        create_handler: impl FnOnce(Server<P, T>) -> H,
557    ) -> (HandlerTask<T, H>, Server<P, T>)
558    where
559        P: DispatchServerMessage<H, T>,
560        T: HasExecutor + 'static,
561        H: Send + 'static,
562    {
563        let executor = self.executor();
564        Self::spawn_full_on_with(self, create_handler, &executor)
565    }
566
567    /// Spawns a dispatcher for the given server end with a handler on the
568    /// default executor for the transport.
569    ///
570    /// Returns the join handle for the spawned task and the server.
571    pub fn spawn_full<H>(self, handler: H) -> (HandlerTask<T, H>, Server<P, T>)
572    where
573        P: DispatchServerMessage<H, T>,
574        T: HasExecutor + 'static,
575        H: Send + 'static,
576    {
577        self.spawn_full_with(|_| handler)
578    }
579
580    /// Spawns a dispatcher for the given server end with a handler computed
581    /// from a closure on the default executor for the transport.
582    ///
583    /// Returns the join handle for the spawned task.
584    pub fn spawn_with<H>(self, create_handler: impl FnOnce(Server<P, T>) -> H) -> HandlerTask<T, H>
585    where
586        P: DispatchServerMessage<H, T>,
587        T: HasExecutor + 'static,
588        H: Send + 'static,
589    {
590        let executor = self.executor();
591        Self::spawn_on_with(self, create_handler, &executor)
592    }
593
594    /// Spawns a dispatcher for the given server end with a handler on the
595    /// default executor for the transport.
596    ///
597    /// Returns the join handle for the spawned task.
598    pub fn spawn<H>(self, handler: H) -> HandlerTask<T, H>
599    where
600        P: DispatchServerMessage<H, T>,
601        T: HasExecutor + 'static,
602        H: Send + 'static,
603    {
604        self.spawn_with(|_| handler)
605    }
606}