fidl_next_bind/
service.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::marker::PhantomData;
6use core::ops::Deref;
7
8use fidl_next_protocol::ServiceHandler;
9
10/// A discoverable service.
11pub trait DiscoverableService {
12    /// The name of this service.
13    const SERVICE_NAME: &'static str;
14    /// The members of this service.
15    const MEMBER_NAMES: &'static [&'static str];
16}
17
18/// A trait indicating that a service has members of the given type.
19///
20/// Services are currently limited to only having protocol members with a single
21/// type, so only one instance of this trait will be implemented for each
22/// service.
23pub trait HasServiceRequest<T> {}
24
25/// A FIDL service.
26///
27/// # Safety
28///
29/// The associated `Connector` type must be a `#[repr(transparent)]` wrapper
30/// around `C`.
31pub trait Service<C>: DiscoverableService {
32    /// The connector for the service. It must be a `#[repr(transparent)]`
33    /// wrapper around `C`.
34    type Connector;
35}
36
37/// A strongly-typed member connector for a FIDL service.
38#[repr(transparent)]
39pub struct ServiceConnector<S, C> {
40    connector: C,
41    service: PhantomData<S>,
42}
43
44unsafe impl<S, C: Send> Send for ServiceConnector<S, C> {}
45unsafe impl<S, C: Sync> Sync for ServiceConnector<S, C> {}
46
47impl<S, C> ServiceConnector<S, C> {
48    /// Returns a new `ServiceConnector`from an untyped service connector.
49    pub fn from_untyped(connector: C) -> Self {
50        Self { connector, service: PhantomData }
51    }
52}
53
54impl<S: Service<C>, C> Deref for ServiceConnector<S, C> {
55    type Target = S::Connector;
56
57    fn deref(&self) -> &Self::Target {
58        // SAFETY: `S::Connector` is a `#[repr(transparent)]` wrapper around `C`.
59        unsafe { &*(self as *const Self).cast::<S::Connector>() }
60    }
61}
62
63/// A trait that can be implemented to transform service instance
64/// transport handles from their parent server's transport handles.
65pub trait InstanceFromServiceTransport<T> {
66    /// Converts the given service transport handle of type `T` to [`Self`]
67    fn from_service_transport(handle: T) -> Self;
68}
69
70/// A given transport can always be converted to itself
71impl<T> InstanceFromServiceTransport<T> for T {
72    fn from_service_transport(handle: T) -> Self {
73        handle
74    }
75}
76
77/// A service which dispatches incoming connections to a handler.
78pub trait DispatchServiceHandler<
79    H,
80    #[cfg(feature = "fuchsia")] T = zx::Channel,
81    #[cfg(not(feature = "fuchsia"))] T,
82>
83{
84    /// Handles a received connection request with the given handler.
85    fn on_connection(handler: &H, member: &str, server_end: T);
86}
87
88/// An adapter for a FIDL service handler.
89pub struct ServiceHandlerAdapter<S, H> {
90    handler: H,
91    _service: PhantomData<S>,
92}
93
94impl<S, H: Clone> Clone for ServiceHandlerAdapter<S, H> {
95    fn clone(&self) -> Self {
96        Self { handler: self.handler.clone(), _service: PhantomData }
97    }
98}
99
100unsafe impl<S, H> Send for ServiceHandlerAdapter<S, H> where H: Send {}
101unsafe impl<S, H> Sync for ServiceHandlerAdapter<S, H> where H: Sync {}
102
103impl<S, H> ServiceHandlerAdapter<S, H> {
104    /// Creates a new service handler from a supported handler.
105    pub fn from_untyped(handler: H) -> Self {
106        Self { handler, _service: PhantomData }
107    }
108}
109
110impl<S, H, T> ServiceHandler<T> for ServiceHandlerAdapter<S, H>
111where
112    S: DispatchServiceHandler<H, T>,
113{
114    fn on_connection(&self, member: &str, server_end: T) {
115        S::on_connection(&self.handler, member, server_end)
116    }
117}