fidl_next_bind/
client.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::future::Future;
6use core::marker::PhantomData;
7use core::ops::Deref;
8
9use fidl_next_protocol::{self as protocol, ClientHandler, IgnoreEvents, ProtocolError, Transport};
10
11use crate::{ClientEnd, Protocol};
12
13/// A strongly typed client sender.
14#[repr(transparent)]
15pub struct ClientSender<
16    P,
17    #[cfg(feature = "fuchsia")] T: Transport = zx::Channel,
18    #[cfg(not(feature = "fuchsia"))] T: Transport,
19> {
20    sender: protocol::ClientSender<T>,
21    _protocol: PhantomData<P>,
22}
23
24unsafe impl<P, T> Send for ClientSender<P, T>
25where
26    T: Transport,
27    protocol::ClientSender<T>: Send,
28{
29}
30
31impl<P, T: Transport> ClientSender<P, T> {
32    /// Wraps an untyped sender reference, returning a typed sender reference.
33    pub fn wrap_untyped(client: &protocol::ClientSender<T>) -> &Self {
34        unsafe { &*(client as *const protocol::ClientSender<T>).cast() }
35    }
36
37    /// Closes the channel from the client end.
38    pub fn close(&self) {
39        self.sender.close();
40    }
41}
42
43impl<P, T: Transport> Clone for ClientSender<P, T> {
44    fn clone(&self) -> Self {
45        Self { sender: self.sender.clone(), _protocol: PhantomData }
46    }
47}
48
49impl<P: Protocol<T>, T: Transport> Deref for ClientSender<P, T> {
50    type Target = P::ClientSender;
51
52    fn deref(&self) -> &Self::Target {
53        // SAFETY: `P::ClientSender` is a `#[repr(transparent)]` wrapper around `ClientSender<T>`.
54        unsafe { &*(self as *const Self).cast::<P::ClientSender>() }
55    }
56}
57
58/// A protocol which dispatches incoming client messages to a handler.
59pub trait DispatchClientMessage<
60    H,
61    #[cfg(feature = "fuchsia")] T: Transport = zx::Channel,
62    #[cfg(not(feature = "fuchsia"))] T: Transport,
63>: Sized + 'static
64{
65    /// Handles a received client event with the given handler.
66    fn on_event(
67        handler: &mut H,
68        sender: &ClientSender<Self, T>,
69        ordinal: u64,
70        buffer: T::RecvBuffer,
71    ) -> impl Future<Output = ()> + Send;
72}
73
74/// An adapter for a client protocol handler.
75pub struct ClientHandlerAdapter<P, H> {
76    handler: H,
77    _protocol: PhantomData<P>,
78}
79
80unsafe impl<P, H> Send for ClientHandlerAdapter<P, H> where H: Send {}
81
82impl<P, H> ClientHandlerAdapter<P, H> {
83    /// Creates a new protocol client handler from a supported handler.
84    pub fn from_untyped(handler: H) -> Self {
85        Self { handler, _protocol: PhantomData }
86    }
87}
88
89impl<P, H, T> ClientHandler<T> for ClientHandlerAdapter<P, H>
90where
91    P: DispatchClientMessage<H, T>,
92    T: Transport,
93{
94    fn on_event(
95        &mut self,
96        sender: &protocol::ClientSender<T>,
97        ordinal: u64,
98        buffer: T::RecvBuffer,
99    ) -> impl Future<Output = ()> + Send {
100        P::on_event(&mut self.handler, ClientSender::wrap_untyped(sender), ordinal, buffer)
101    }
102}
103
104/// A strongly typed client.
105pub struct Client<
106    P,
107    #[cfg(feature = "fuchsia")] T: Transport = zx::Channel,
108    #[cfg(not(feature = "fuchsia"))] T: Transport,
109> {
110    client: protocol::Client<T>,
111    _protocol: PhantomData<P>,
112}
113
114unsafe impl<P, T> Send for Client<P, T>
115where
116    T: Transport,
117    protocol::Client<T>: Send,
118{
119}
120
121impl<P, T: Transport> Client<P, T> {
122    /// Creates a new client from a client end.
123    pub fn new(client_end: ClientEnd<P, T>) -> Self {
124        Self { client: protocol::Client::new(client_end.into_untyped()), _protocol: PhantomData }
125    }
126
127    /// Returns the sender for the client.
128    pub fn sender(&self) -> &ClientSender<P, T> {
129        ClientSender::wrap_untyped(self.client.sender())
130    }
131
132    /// Creates a new client from an untyped client.
133    pub fn from_untyped(client: protocol::Client<T>) -> Self {
134        Self { client, _protocol: PhantomData }
135    }
136
137    /// Runs the client with the provided handler.
138    pub async fn run<H>(self, handler: H) -> Result<H, ProtocolError<T::Error>>
139    where
140        P: DispatchClientMessage<H, T>,
141    {
142        self.client
143            .run(ClientHandlerAdapter { handler, _protocol: PhantomData::<P> })
144            .await
145            .map(|adapter| adapter.handler)
146    }
147
148    /// Runs the client, ignoring any incoming events.
149    pub async fn run_sender(self) -> Result<(), ProtocolError<T::Error>> {
150        self.client.run(IgnoreEvents).await.map(|_| ())
151    }
152}