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