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