fuchsia_component_client/
fidl_next.rs

1// Copyright 2025 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
5//! Implementations for new Rust bindings.
6
7use anyhow::Context;
8use fidl_next::protocol::ServiceConnector as ServiceConnectorTrait;
9use fidl_next::{ClientEnd, Discoverable, DiscoverableService, ServerEnd, Service};
10
11use super::{Error, SVC_DIR, connect_channel_to_protocol_at_path};
12
13/// A connector for a FIDL service instance that uses a Zircon channel.
14#[repr(transparent)]
15pub struct InstanceConnector(zx::Channel);
16
17impl ServiceConnectorTrait<zx::Channel> for InstanceConnector {
18    type Error = Error;
19
20    fn connect_to_member(&self, member: &str, server_end: zx::Channel) -> Result<(), Self::Error> {
21        fdio::service_connect_at(&self.0, member, server_end).context("failed to connect to member")
22    }
23}
24
25/// Connect to a FIDL protocol using the provided server end and namespace
26/// prefix.
27pub fn connect_server_end_to_protocol_at<P: Discoverable>(
28    server_end: ServerEnd<P, zx::Channel>,
29    service_directory_path: &str,
30) -> Result<(), Error> {
31    let protocol_path = format!("{}/{}", service_directory_path, P::PROTOCOL_NAME);
32    connect_channel_to_protocol_at_path(server_end.into_untyped(), &protocol_path)
33}
34
35/// Connect to a FIDL protocol using the provided namespace prefix.
36pub fn connect_to_protocol_at<P: Discoverable>(
37    service_prefix: &str,
38) -> Result<ClientEnd<P, zx::Channel>, Error> {
39    let (client_end, server_end) = fidl_next::fuchsia::create_channel();
40    let () = connect_server_end_to_protocol_at(server_end, service_prefix)?;
41    Ok(client_end)
42}
43
44/// Connect to a FIDL protocol in the `/svc` directory of the application's root
45/// namespace.
46pub fn connect_to_protocol<P: Discoverable>() -> Result<ClientEnd<P, zx::Channel>, Error> {
47    connect_to_protocol_at(SVC_DIR)
48}
49
50/// Connect to a FIDL service instance in the `/svc` directory of the application's
51/// root namespace.
52pub fn connect_to_service_instance<S>(instance: &str) -> Result<S::Connector, Error>
53where
54    S: DiscoverableService + Service<InstanceConnector>,
55{
56    let service_path = format!("{}/{}/{}", SVC_DIR, S::SERVICE_NAME, instance);
57    let (client, server) = zx::Channel::create();
58    fuchsia_fs::directory::open_channel_in_namespace(
59        &service_path,
60        fidl_fuchsia_io::Flags::PROTOCOL_DIRECTORY
61            | fidl_fuchsia_io::Flags::PERM_CONNECT
62            | fidl_fuchsia_io::Flags::PERM_ENUMERATE,
63        server.into(),
64    )?;
65    let connector = InstanceConnector(client);
66    // SAFETY: The `Service` trait guarantees that `S::Connector` is a
67    // `#[repr(transparent)]` wrapper around the generic connector type.
68    let connector = std::mem::ManuallyDrop::new(connector);
69    Ok(unsafe { std::ptr::read(&*connector as *const InstanceConnector as *const S::Connector) })
70}