Skip to content

Commit 2d6a916

Browse files
committed
Add NodeBuilder
1 parent 865e203 commit 2d6a916

File tree

1 file changed

+81
-0
lines changed

1 file changed

+81
-0
lines changed

rclrs/src/node/mod.rs

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,28 @@ pub struct Node {
4040
pub(crate) subscriptions: Vec<Weak<dyn SubscriptionBase>>,
4141
}
4242

43+
/// A builder for node instantiation.
44+
///
45+
/// default value in each fields are
46+
/// - context: user defined
47+
/// - name: user defined
48+
/// - namespace: "/"
49+
///
50+
/// # Example
51+
/// ```
52+
/// # use rclrs::{Context, Node, NodeBuilder, RclReturnCode};
53+
/// let context = Context::new([])?;
54+
/// let node = NodeBuilder::new("foo_node", &context).namespace("/bar").build()?;
55+
/// assert_eq!(node.name(), "foo_node");
56+
/// assert_eq!(node.namespace(), "/bar");
57+
/// # Ok::<(), RclReturnCode>(())
58+
/// ```
59+
pub struct NodeBuilder<'a> {
60+
pub(self) context: &'a Context,
61+
pub(self) name: &'a str,
62+
pub(self) namespace: &'a str,
63+
}
64+
4365
impl Node {
4466
/// Creates a new node in the empty namespace.
4567
#[allow(clippy::new_ret_no_self)]
@@ -246,3 +268,62 @@ impl Node {
246268
domain_id
247269
}
248270
}
271+
272+
impl<'a> NodeBuilder<'a> {
273+
/// Creates new builder for Node.
274+
pub fn new(name: &'a str, context: &'a Context) -> NodeBuilder<'a> {
275+
let mut default_domain_id = 0;
276+
// SAFETY: No preconditions for this function.
277+
let ret = unsafe { rcl_get_default_domain_id(&mut default_domain_id) };
278+
debug_assert_eq!(ret, 0);
279+
280+
NodeBuilder {
281+
context,
282+
name,
283+
namespace: "/",
284+
}
285+
}
286+
287+
/// Sets node namespace.
288+
pub fn namespace(mut self, namespace: &'a str) -> Self {
289+
self.namespace = namespace;
290+
self
291+
}
292+
293+
/// Builds node instance
294+
pub fn build(&self) -> Result<Node, RclReturnCode> {
295+
let node_name = CString::new(self.name).unwrap();
296+
let node_namespace = CString::new(self.namespace).unwrap();
297+
298+
// SAFETY: No preconditions for this function.
299+
let mut node_handle = unsafe { rcl_get_zero_initialized_node() };
300+
301+
unsafe {
302+
// SAFETY: No preconditions for this function.
303+
let context_handle = &mut *self.context.handle.lock();
304+
// SAFETY: No preconditions for this function.
305+
let node_options = rcl_node_get_default_options();
306+
307+
// SAFETY: The node handle is zero-initialized as expected by this function.
308+
// The strings and node options are copied by this function, so we don't need
309+
// to keep them alive.
310+
// The context handle has to be kept alive because it is co-owned by the node.
311+
rcl_node_init(
312+
&mut node_handle,
313+
node_name.as_ptr(),
314+
node_namespace.as_ptr(),
315+
context_handle,
316+
&node_options,
317+
)
318+
.ok()?;
319+
};
320+
321+
let handle = Arc::new(Mutex::new(node_handle));
322+
323+
Ok(Node {
324+
handle,
325+
context: self.context.handle.clone(),
326+
subscriptions: std::vec![],
327+
})
328+
}
329+
}

0 commit comments

Comments
 (0)