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