fdf_component/node.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
// Copyright 2024 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use fidl::endpoints::ClientEnd;
use fidl_fuchsia_driver_framework::{
NodeAddArgs, NodeControllerMarker, NodeMarker, NodeProperty, NodeProxy, Offer,
};
use tracing::error;
use zx::Status;
mod offers;
mod properties;
pub use offers::*;
pub use properties::*;
/// Holds on to a [`NodeProxy`] and provides simplified methods for adding child nodes.
pub struct Node(NodeProxy);
impl Node {
/// Adds an owned child node to this node and returns the [`ClientEnd`]s for its
/// `NodeController` and `Node`. Use a [`NodeBuilder`] to create the `args` argument.
///
/// If you don't need the `NodeController`, it is safe to drop it, but the node will be removed
/// if the client end for the `Node` is dropped.
///
/// Logs an error message and returns [`Status::INTERNAL`] if there's an error adding the
/// child node.
pub async fn add_owned_child(
&self,
args: NodeAddArgs,
) -> Result<(ClientEnd<NodeMarker>, ClientEnd<NodeControllerMarker>), Status> {
let (child_controller, child_controller_server) = fidl::endpoints::create_endpoints();
let (child_node, child_node_server) = fidl::endpoints::create_endpoints();
self.proxy()
.add_child(args, child_controller_server, Some(child_node_server))
.await
.map_err(|err| {
error!("transport error trying to create child node: {err}");
Status::INTERNAL
})?
.map_err(|err| {
error!("failed to create child node: {err:?}");
Status::INTERNAL
})?;
Ok((child_node, child_controller))
}
/// Adds an owned child node to this node and returns the [`ClientEnd`]s for its
/// `NodeController`. Use a [`NodeBuilder`] to create the `args` argument.
///
/// If you don't need the `NodeController`, it is safe to drop it. The driver runtime will
/// attempt to find a driver to bind the node to.
///
/// Logs an error message and returns [`Status::INTERNAL`] if there's an error adding the
/// child node.
pub async fn add_child(
&self,
args: NodeAddArgs,
) -> Result<ClientEnd<NodeControllerMarker>, Status> {
let (child_controller, child_controller_server) = fidl::endpoints::create_endpoints();
self.proxy()
.add_child(args, child_controller_server, None)
.await
.map_err(|err| {
error!("transport error trying to create child node: {err}");
Status::INTERNAL
})?
.map_err(|err| {
error!("failed to create child node: {err:?}");
Status::INTERNAL
})?;
Ok(child_controller)
}
/// Accesses the underlying [`NodeProxy`].
pub fn proxy(&self) -> &NodeProxy {
&self.0
}
}
impl From<NodeProxy> for Node {
fn from(value: NodeProxy) -> Self {
Node(value)
}
}
/// A builder for adding a child node to an existing [`Node`].
pub struct NodeBuilder(NodeAddArgs);
impl NodeBuilder {
/// Creates a new [`NodeAddBuilder`] with the given `node_name` already set.
pub fn new(node_name: impl Into<String>) -> Self {
Self(NodeAddArgs { name: Some(node_name.into()), ..Default::default() })
}
/// Adds a property to the node. The `key` argument is something that can convert to a
/// [`PropertyKey`], which includes strings and [`u32`] integers. The `value` argument is
/// something that can convert into a [`PropertyValue`], which includes strings, [`u32`]
/// integers, and [`bool`] values.
pub fn add_property(
mut self,
key: impl Into<PropertyKey>,
value: impl Into<PropertyValue>,
) -> Self {
let key = key.into().0;
let value = value.into().0;
self.0.properties.get_or_insert_with(|| vec![]).push(NodeProperty { key, value });
self
}
/// Adds a service offer to the node. The `offer` can be built with the
/// [`offers::ZirconServiceOffer`] builder.
pub fn add_offer(mut self, offer: Offer) -> Self {
self.0.offers2.get_or_insert_with(|| vec![]).push(offer);
self
}
/// Finalize the construction of the node for use with [`Node::add_child`] or
/// [`Node::add_owned_child`].
pub fn build(self) -> NodeAddArgs {
self.0
}
}