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