@@ -40,6 +40,28 @@ pub struct Node {
40
40
pub ( crate ) subscriptions : Vec < Weak < dyn SubscriptionBase > > ,
41
41
}
42
42
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
+
43
65
impl Node {
44
66
/// Creates a new node in the empty namespace.
45
67
#[ allow( clippy:: new_ret_no_self) ]
@@ -246,3 +268,62 @@ impl Node {
246
268
domain_id
247
269
}
248
270
}
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