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