Skip to main content

fidl_next_bind/
server.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_codec::{Encode, Wire};
10use fidl_next_protocol::{
11    self as protocol, LocalServerHandler, Message, ProtocolError, ServerHandler, Transport,
12};
13
14use crate::{
15    HasConnectionHandles, HasTransport, Method, Respond, RespondErr, RespondFuture, ServerEnd,
16    TwoWayMethod,
17};
18
19/// A strongly typed server.
20#[repr(transparent)]
21pub struct Server<P, T: Transport = <P as HasTransport>::Transport> {
22    server: protocol::Server<T>,
23    _protocol: PhantomData<P>,
24}
25
26unsafe impl<P, T> Send for Server<P, T>
27where
28    protocol::Server<T>: Send,
29    T: Transport,
30{
31}
32
33impl<P, T: Transport> Server<P, T> {
34    /// Creates a new server handle from an untyped server handle.
35    pub fn from_untyped(server: protocol::Server<T>) -> Self {
36        Self { server, _protocol: PhantomData }
37    }
38
39    /// Closes the channel from the server end.
40    pub fn close(&self) {
41        self.server.close();
42    }
43
44    /// Closes the channel from the server end without sending an epitaph.
45    pub fn close_with_epitaph(&self, epitaph: i32) {
46        self.server.close_with_epitaph(epitaph);
47    }
48}
49
50impl<P, T: Transport> Clone for Server<P, T> {
51    fn clone(&self) -> Self {
52        Self { server: self.server.clone(), _protocol: PhantomData }
53    }
54}
55
56impl<P: HasConnectionHandles<T>, T: Transport> Deref for Server<P, T> {
57    type Target = P::Server;
58
59    fn deref(&self) -> &Self::Target {
60        // SAFETY: `P::Server` is a `#[repr(transparent)]` wrapper around
61        // `Server<T>`.
62        unsafe { &*(self as *const Self).cast::<P::Server>() }
63    }
64}
65
66/// A protocol which dispatches incoming server messages to a local handler.
67///
68/// This is a variant of [`DispatchServerMessage`] that does not require
69/// implementing `Send` and only supports local-thread executors.
70pub trait DispatchLocalServerMessage<H, T: Transport>: Sized + 'static {
71    /// Handles a received server one-way message with the given handler.
72    fn on_one_way(
73        handler: &mut H,
74        message: Message<T>,
75    ) -> impl Future<Output = Result<(), ProtocolError<T::Error>>>;
76
77    /// Handles a received server two-way message with the given handler.
78    fn on_two_way(
79        handler: &mut H,
80        message: Message<T>,
81        responder: protocol::Responder<T>,
82    ) -> impl Future<Output = Result<(), ProtocolError<T::Error>>>;
83}
84
85/// A protocol which dispatches incoming server messages to a handler.
86pub trait DispatchServerMessage<H, T: Transport>: Sized + 'static {
87    /// Handles a received server one-way message with the given handler.
88    fn on_one_way(
89        handler: &mut H,
90        message: Message<T>,
91    ) -> impl Future<Output = Result<(), ProtocolError<T::Error>>> + Send;
92
93    /// Handles a received server two-way message with the given handler.
94    fn on_two_way(
95        handler: &mut H,
96        message: Message<T>,
97        responder: protocol::Responder<T>,
98    ) -> impl Future<Output = Result<(), ProtocolError<T::Error>>> + Send;
99}
100
101/// An adapter for a server protocol handler.
102pub struct ServerHandlerToProtocolAdapter<P, H> {
103    handler: H,
104    _protocol: PhantomData<P>,
105}
106
107unsafe impl<P, H> Send for ServerHandlerToProtocolAdapter<P, H> where H: Send {}
108
109impl<P, H> ServerHandlerToProtocolAdapter<P, H> {
110    /// Creates a new protocol server handler from a supported handler.
111    pub fn from_untyped(handler: H) -> Self {
112        Self { handler, _protocol: PhantomData }
113    }
114}
115
116impl<P, H, T> LocalServerHandler<T> for ServerHandlerToProtocolAdapter<P, H>
117where
118    P: DispatchLocalServerMessage<H, T>,
119    T: Transport,
120{
121    fn on_one_way(
122        &mut self,
123        message: Message<T>,
124    ) -> impl Future<Output = Result<(), ProtocolError<<T as Transport>::Error>>> {
125        P::on_one_way(&mut self.handler, message)
126    }
127
128    fn on_two_way(
129        &mut self,
130        message: Message<T>,
131        responder: fidl_next_protocol::Responder<T>,
132    ) -> impl Future<Output = Result<(), ProtocolError<<T as Transport>::Error>>> {
133        P::on_two_way(&mut self.handler, message, responder)
134    }
135}
136
137impl<P, H, T> ServerHandler<T> for ServerHandlerToProtocolAdapter<P, H>
138where
139    P: DispatchServerMessage<H, T>,
140    H: Send,
141    T: Transport,
142{
143    fn on_one_way(
144        &mut self,
145        message: Message<T>,
146    ) -> impl Future<Output = Result<(), ProtocolError<T::Error>>> + Send {
147        P::on_one_way(&mut self.handler, message)
148    }
149
150    fn on_two_way(
151        &mut self,
152        message: Message<T>,
153        responder: protocol::Responder<T>,
154    ) -> impl Future<Output = Result<(), ProtocolError<T::Error>>> + Send {
155        P::on_two_way(&mut self.handler, message, responder)
156    }
157}
158
159/// A strongly typed server.
160pub struct ServerDispatcher<P, T: Transport = <P as HasTransport>::Transport> {
161    dispatcher: protocol::ServerDispatcher<T>,
162    _protocol: PhantomData<P>,
163}
164
165unsafe impl<P, T> Send for ServerDispatcher<P, T>
166where
167    protocol::Server<T>: Send,
168    T: Transport,
169{
170}
171
172impl<P, T: Transport> ServerDispatcher<P, T> {
173    /// Creates a new server dispatcher from a server end.
174    pub fn new(server_end: ServerEnd<P, T>) -> Self {
175        Self {
176            dispatcher: protocol::ServerDispatcher::new(server_end.into_untyped()),
177            _protocol: PhantomData,
178        }
179    }
180
181    /// Returns the dispatcher's server.
182    pub fn server(&self) -> Server<P, T> {
183        Server::from_untyped(self.dispatcher.server())
184    }
185
186    /// Creates a new server dispatcher from an untyped server dispatcher.
187    pub fn from_untyped(server: protocol::ServerDispatcher<T>) -> Self {
188        Self { dispatcher: server, _protocol: PhantomData }
189    }
190
191    /// Runs the server with the provided handler.
192    pub async fn run<H>(self, handler: H) -> Result<H, ProtocolError<T::Error>>
193    where
194        P: DispatchServerMessage<H, T>,
195        H: Send,
196    {
197        self.dispatcher
198            .run(ServerHandlerToProtocolAdapter { handler, _protocol: PhantomData::<P> })
199            .await
200            .map(|adapter| adapter.handler)
201    }
202
203    /// Runs the server locally with the provided handler.
204    pub async fn run_local<H>(self, handler: H) -> Result<H, ProtocolError<T::Error>>
205    where
206        P: DispatchLocalServerMessage<H, T>,
207    {
208        self.dispatcher
209            .run_local(ServerHandlerToProtocolAdapter { handler, _protocol: PhantomData::<P> })
210            .await
211            .map(|adapter| adapter.handler)
212    }
213}
214
215/// A strongly typed `Responder`.
216#[must_use]
217pub struct Responder<M, T: Transport = <<M as Method>::Protocol as HasTransport>::Transport> {
218    responder: protocol::Responder<T>,
219    _method: PhantomData<M>,
220}
221
222impl<M, T: Transport> Responder<M, T> {
223    /// Creates a new responder.
224    pub fn from_untyped(responder: protocol::Responder<T>) -> Self {
225        Self { responder, _method: PhantomData }
226    }
227
228    /// Responds to the client.
229    ///
230    /// For methods which return a result, this method implicitly returns `Ok`
231    /// of the given response.
232    pub fn respond<R>(self, response: R) -> RespondFuture<T>
233    where
234        M: TwoWayMethod + Respond<R>,
235        M::Response: Wire<Constraint = ()>,
236        <M as Respond<R>>::Output: Encode<M::Response, T::SendBuffer>,
237    {
238        self.respond_with(M::respond(response))
239    }
240
241    /// Responds `Err` to the client.
242    pub fn respond_err<R>(self, response: R) -> RespondFuture<T>
243    where
244        M: TwoWayMethod + RespondErr<R>,
245        M::Response: Wire<Constraint = ()>,
246        <M as RespondErr<R>>::Output: Encode<M::Response, T::SendBuffer>,
247    {
248        self.respond_with(M::respond_err(response))
249    }
250
251    /// Responds to the client.
252    pub fn respond_with<R>(self, response: R) -> RespondFuture<T>
253    where
254        M: TwoWayMethod,
255        M::Response: Wire<Constraint = ()>,
256        R: Encode<M::Response, T::SendBuffer>,
257    {
258        RespondFuture::from_untyped(self.responder.respond(M::ORDINAL, M::FLEXIBILITY, response))
259    }
260}