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