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, 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 handler.
67pub trait DispatchServerMessage<H, T: Transport>: Sized + 'static {
68    /// Handles a received server one-way message with the given handler.
69    fn on_one_way(
70        handler: &mut H,
71        ordinal: u64,
72        flexibility: Flexibility,
73        body: Body<T>,
74    ) -> impl Future<Output = Result<(), ProtocolError<T::Error>>> + Send;
75
76    /// Handles a received server two-way message with the given handler.
77    fn on_two_way(
78        handler: &mut H,
79        ordinal: u64,
80        flexibility: Flexibility,
81        body: Body<T>,
82        responder: protocol::Responder<T>,
83    ) -> impl Future<Output = Result<(), ProtocolError<T::Error>>> + Send;
84}
85
86/// An adapter for a server protocol handler.
87pub struct ServerHandlerAdapter<P, H> {
88    handler: H,
89    _protocol: PhantomData<P>,
90}
91
92unsafe impl<P, H> Send for ServerHandlerAdapter<P, H> where H: Send {}
93
94impl<P, H> ServerHandlerAdapter<P, H> {
95    /// Creates a new protocol server handler from a supported handler.
96    pub fn from_untyped(handler: H) -> Self {
97        Self { handler, _protocol: PhantomData }
98    }
99}
100
101impl<P, H, T> ServerHandler<T> for ServerHandlerAdapter<P, H>
102where
103    P: DispatchServerMessage<H, T>,
104    T: Transport,
105{
106    fn on_one_way(
107        &mut self,
108        ordinal: u64,
109        flexibility: Flexibility,
110        body: Body<T>,
111    ) -> impl Future<Output = Result<(), ProtocolError<T::Error>>> + Send {
112        P::on_one_way(&mut self.handler, ordinal, flexibility, body)
113    }
114
115    fn on_two_way(
116        &mut self,
117        ordinal: u64,
118        flexibility: Flexibility,
119        body: Body<T>,
120        responder: protocol::Responder<T>,
121    ) -> impl Future<Output = Result<(), ProtocolError<T::Error>>> + Send {
122        P::on_two_way(&mut self.handler, ordinal, flexibility, body, responder)
123    }
124}
125
126/// A strongly typed server.
127pub struct ServerDispatcher<P, T: Transport = <P as HasTransport>::Transport> {
128    dispatcher: protocol::ServerDispatcher<T>,
129    _protocol: PhantomData<P>,
130}
131
132unsafe impl<P, T> Send for ServerDispatcher<P, T>
133where
134    protocol::Server<T>: Send,
135    T: Transport,
136{
137}
138
139impl<P, T: Transport> ServerDispatcher<P, T> {
140    /// Creates a new server dispatcher from a server end.
141    pub fn new(server_end: ServerEnd<P, T>) -> Self {
142        Self {
143            dispatcher: protocol::ServerDispatcher::new(server_end.into_untyped()),
144            _protocol: PhantomData,
145        }
146    }
147
148    /// Returns the dispatcher's server.
149    pub fn server(&self) -> Server<P, T> {
150        Server::from_untyped(self.dispatcher.server())
151    }
152
153    /// Creates a new server dispatcher from an untyped server dispatcher.
154    pub fn from_untyped(server: protocol::ServerDispatcher<T>) -> Self {
155        Self { dispatcher: server, _protocol: PhantomData }
156    }
157
158    /// Runs the server with the provided handler.
159    pub async fn run<H>(self, handler: H) -> Result<H, ProtocolError<T::Error>>
160    where
161        P: DispatchServerMessage<H, T>,
162        H: Send,
163    {
164        self.dispatcher
165            .run(ServerHandlerAdapter { handler, _protocol: PhantomData::<P> })
166            .await
167            .map(|adapter| adapter.handler)
168    }
169}
170
171/// A strongly typed `Responder`.
172#[must_use]
173pub struct Responder<M, T: Transport = <<M as Method>::Protocol as HasTransport>::Transport> {
174    responder: protocol::Responder<T>,
175    _method: PhantomData<M>,
176}
177
178impl<M, T: Transport> Responder<M, T> {
179    /// Creates a new responder.
180    pub fn from_untyped(responder: protocol::Responder<T>) -> Self {
181        Self { responder, _method: PhantomData }
182    }
183
184    /// Responds to the client.
185    ///
186    /// For methods which return a result, this method implicitly returns `Ok`
187    /// of the given response.
188    pub fn respond<R>(self, response: R) -> RespondFuture<T>
189    where
190        M: TwoWayMethod + Respond<R>,
191        M::Response: Wire<Constraint = ()>,
192        <M as Respond<R>>::Output: Encode<M::Response, T::SendBuffer>,
193    {
194        self.respond_with(M::respond(response))
195    }
196
197    /// Responds `Err` to the client.
198    pub fn respond_err<R>(self, response: R) -> RespondFuture<T>
199    where
200        M: TwoWayMethod + RespondErr<R>,
201        M::Response: Wire<Constraint = ()>,
202        <M as RespondErr<R>>::Output: Encode<M::Response, T::SendBuffer>,
203    {
204        self.respond_with(M::respond_err(response))
205    }
206
207    /// Responds to the client.
208    pub fn respond_with<R>(self, response: R) -> RespondFuture<T>
209    where
210        M: TwoWayMethod,
211        M::Response: Wire<Constraint = ()>,
212        R: Encode<M::Response, T::SendBuffer>,
213    {
214        RespondFuture::from_untyped(self.responder.respond(M::ORDINAL, M::FLEXIBILITY, response))
215    }
216}