Skip to content

Commit a627c3c

Browse files
committed
Migrate create_client to use impl Into<ClientOptions>
Signed-off-by: Michael X. Grey <[email protected]>
1 parent c7f78ee commit a627c3c

File tree

3 files changed

+72
-9
lines changed

3 files changed

+72
-9
lines changed

rclrs/src/client.rs

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use rosidl_runtime_rs::Message;
1111
use crate::{
1212
error::{RclReturnCode, ToResult},
1313
rcl_bindings::*,
14-
MessageCow, NodeHandle, RclrsError, ENTITY_LIFECYCLE_MUTEX,
14+
IntoPrimitiveOptions, MessageCow, NodeHandle, RclrsError, ENTITY_LIFECYCLE_MUTEX, QoSProfile,
1515
};
1616

1717
// SAFETY: The functions accessing this type, including drop(), shouldn't care about the thread
@@ -83,23 +83,28 @@ where
8383
T: rosidl_runtime_rs::Service,
8484
{
8585
/// Creates a new client.
86-
pub(crate) fn new(node_handle: Arc<NodeHandle>, topic: &str) -> Result<Self, RclrsError>
86+
pub(crate) fn new<'a>(
87+
node_handle: Arc<NodeHandle>,
88+
options: impl Into<ClientOptions<'a>>,
89+
) -> Result<Self, RclrsError>
8790
// This uses pub(crate) visibility to avoid instantiating this struct outside
8891
// [`Node::create_client`], see the struct's documentation for the rationale
8992
where
9093
T: rosidl_runtime_rs::Service,
9194
{
95+
let ClientOptions { service_name, qos } = options.into();
9296
// SAFETY: Getting a zero-initialized value is always safe.
9397
let mut rcl_client = unsafe { rcl_get_zero_initialized_client() };
9498
let type_support = <T as rosidl_runtime_rs::Service>::get_type_support()
9599
as *const rosidl_service_type_support_t;
96-
let topic_c_string = CString::new(topic).map_err(|err| RclrsError::StringContainsNul {
100+
let topic_c_string = CString::new(service_name).map_err(|err| RclrsError::StringContainsNul {
97101
err,
98-
s: topic.into(),
102+
s: service_name.into(),
99103
})?;
100104

101105
// SAFETY: No preconditions for this function.
102-
let client_options = unsafe { rcl_client_get_default_options() };
106+
let mut client_options = unsafe { rcl_client_get_default_options() };
107+
client_options.qos = qos.into();
103108

104109
{
105110
let rcl_node = node_handle.rcl_node.lock().unwrap();
@@ -275,6 +280,28 @@ where
275280
}
276281
}
277282

283+
/// `ClientOptions` are used by [`Node::create_client`][1] to initialize a
284+
/// [`Client`] for a service.
285+
///
286+
/// [1]: crate::NodeState::create_client
287+
#[derive(Debug, Clone)]
288+
#[non_exhaustive]
289+
pub struct ClientOptions<'a> {
290+
/// The name of the service that this client will send requests to
291+
pub service_name: &'a str,
292+
/// The quality of the service profile for this client
293+
pub qos: QoSProfile,
294+
}
295+
296+
impl<'a, T: IntoPrimitiveOptions<'a>> From<T> for ClientOptions<'a> {
297+
fn from(value: T) -> Self {
298+
let options = value.into_primitive_options();
299+
let mut qos = QoSProfile::services_default();
300+
options.apply(&mut qos);
301+
Self { service_name: options.name, qos }
302+
}
303+
}
304+
278305
impl<T> ClientBase for Client<T>
279306
where
280307
T: rosidl_runtime_rs::Service,

rclrs/src/node.rs

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use std::{
1919
use rosidl_runtime_rs::Message;
2020

2121
use crate::{
22-
rcl_bindings::*, Client, ClientBase, Clock, ContextHandle, GuardCondition,
22+
rcl_bindings::*, Client, ClientBase, ClientOptions, Clock, ContextHandle, GuardCondition,
2323
ParameterBuilder, ParameterInterface, ParameterVariant, Parameters, Publisher, PublisherOptions,
2424
RclrsError, Service, ServiceBase, ServiceOptions, Subscription, SubscriptionBase, SubscriptionCallback,
2525
SubscriptionOptions, TimeSource, ENTITY_LIFECYCLE_MUTEX,
@@ -215,13 +215,47 @@ impl NodeState {
215215

216216
/// Creates a [`Client`][1].
217217
///
218+
/// Pass in only the service name for the `options` argument to use all default client options:
219+
/// ```
220+
/// # use rclrs::*;
221+
/// # let executor = Context::default().create_basic_executor();
222+
/// # let node = executor.create_node("my_node").unwrap();
223+
/// let client = node.create_client::<test_msgs::srv::Empty>(
224+
/// "my_service"
225+
/// )
226+
/// .unwrap();
227+
/// ```
228+
///
229+
/// Take advantage of the [`IntoPrimitiveOptions`] API to easily build up the
230+
/// client options:
231+
///
232+
/// ```
233+
/// # use rclrs::*;
234+
/// # let executor = Context::default().create_basic_executor();
235+
/// # let node = executor.create_node("my_node").unwrap();
236+
/// let client = node.create_client::<test_msgs::srv::Empty>(
237+
/// "my_service"
238+
/// .keep_all()
239+
/// .transient_local()
240+
/// )
241+
/// .unwrap();
242+
/// ```
243+
///
244+
/// Any quality of service options that you explicitly specify will override
245+
/// the default service options. Any that you do not explicitly specify will
246+
/// remain the default service options. Note that clients are generally
247+
/// expected to use [reliable][2], so it's best not to change the reliability
248+
/// setting unless you know what you are doing.
218249
/// [1]: crate::Client
219250
// TODO: make client's lifetime depend on node's lifetime
220-
pub fn create_client<T>(&self, topic: &str) -> Result<Arc<Client<T>>, RclrsError>
251+
pub fn create_client<'a, T>(
252+
&self,
253+
options: impl Into<ClientOptions<'a>>,
254+
) -> Result<Arc<Client<T>>, RclrsError>
221255
where
222256
T: rosidl_runtime_rs::Service,
223257
{
224-
let client = Arc::new(Client::<T>::new(Arc::clone(&self.handle), topic)?);
258+
let client = Arc::new(Client::<T>::new(Arc::clone(&self.handle), options)?);
225259
{ self.clients_mtx.lock().unwrap() }.push(Arc::downgrade(&client) as Weak<dyn ClientBase>);
226260
Ok(client)
227261
}
@@ -352,7 +386,7 @@ impl NodeState {
352386
/// Any quality of service options that you explicitly specify will override
353387
/// the default service options. Any that you do not explicitly specify will
354388
/// remain the default service options. Note that services are generally
355-
/// expected to use [reliable][2], so is best not to change the reliability
389+
/// expected to use [reliable][2], so it's best not to change the reliability
356390
/// setting unless you know what you are doing.
357391
///
358392
/// [1]: crate::Service

rclrs/src/service.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,8 @@ where
185185

186186
/// `ServiceOptions are used by [`Node::create_service`][1] to initialize a
187187
/// [`Service`] provider.
188+
///
189+
/// [1]: crate::NodeState::create_service
188190
#[derive(Debug, Clone)]
189191
#[non_exhaustive]
190192
pub struct ServiceOptions<'a> {

0 commit comments

Comments
 (0)