Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
191351f
Subject: Configure code formatting (Crate imports, 60 char array width)
Apr 9, 2024
5466d47
Update code formatting configuration through .rustfmt.toml
Apr 9, 2024
2258772
Update code formatting configuration through .rustfmt.toml
Apr 9, 2024
f8bb31a
Update code formatting configuration through .rustfmt.toml
Apr 9, 2024
face334
Update code formatting configuration through .rustfmt.toml
Apr 9, 2024
b516f4c
Update code formatting configuration through .rustfmt.toml
Apr 9, 2024
5718298
Update code formatting configuration through .rustfmt.toml
Apr 9, 2024
1c1e2eb
Update code formatting configuration through .rustfmt.toml
Apr 9, 2024
18ed6b7
Update code formatting configuration through .rustfmt.toml
Apr 9, 2024
47b1b91
Update code formatting configuration through .rustfmt.toml
Apr 9, 2024
168de96
Update code formatting configuration through .rustfmt.toml
Apr 9, 2024
e1a9513
Update code formatting configuration through .rustfmt.toml
Apr 9, 2024
5bab99f
Update code formatting configuration through .rustfmt.toml
Apr 9, 2024
2d07d63
Update code formatting configuration through .rustfmt.toml
Apr 9, 2024
ca64f36
Update code formatting configuration through .rustfmt.toml
Apr 9, 2024
9331899
Update code formatting configuration through .rustfmt.toml
Apr 9, 2024
08b84db
Update code formatting configuration through .rustfmt.toml
Apr 9, 2024
b343904
Update code formatting configuration through .rustfmt.toml
Apr 9, 2024
5a00770
Update code formatting configuration through .rustfmt.toml
Apr 9, 2024
22f8fed
Update code formatting configuration through .rustfmt.toml
Apr 9, 2024
f7cd342
Update code formatting configuration through .rustfmt.toml
Apr 9, 2024
b5d109f
Update code formatting configuration through .rustfmt.toml
Apr 9, 2024
824d738
Update code formatting configuration through .rustfmt.toml
Apr 9, 2024
56945f3
Update code formatting configuration through .rustfmt.toml
Apr 9, 2024
6b15b3a
Update code formatting configuration through .rustfmt.toml
Apr 9, 2024
290a7a5
Update code formatting configuration through .rustfmt.toml
Apr 9, 2024
9556774
Update code formatting configuration through .rustfmt.toml
Apr 9, 2024
651dbb1
Update code formatting configuration through .rustfmt.toml
Apr 9, 2024
3263dc9
Update code formatting configuration through .rustfmt.toml
Apr 9, 2024
5937912
Update code formatting configuration through .rustfmt.toml
Apr 9, 2024
86a85fb
Update code formatting configuration through .rustfmt.toml
Apr 9, 2024
c38872d
Configure code formatting through .rustfmt.toml
Apr 9, 2024
65258d9
Configure code formatting through .rustfmt.toml
Apr 9, 2024
cb191a9
Update code formatting configuration through .rustfmt.toml
Apr 9, 2024
bc10cea
Update code formatting configuration through .rustfmt.toml
Apr 9, 2024
ce6a7ba
Update code formatting configuration through .rustfmt.toml
Apr 9, 2024
f614676
Update code formatting configuration through .rustfmt.toml
Apr 9, 2024
61240d5
Update code formatting configuration through .rustfmt.toml
Apr 9, 2024
e7d9a3a
Configure code formatting through .rustfmt.toml
Apr 9, 2024
b1968ef
Update code formatting configuration through .rustfmt.toml
Apr 9, 2024
6efcd0b
Update code formatting configuration through .rustfmt.toml
Apr 9, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions examples/message_demo/.rustfmt.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
imports_granularity = "Crate"
array_width = 60
attr_fn_like_width = 70
brace_style = "SameLineWhere"
combine_control_expr = false
comment_width = 80
wrap_comments = true
7 changes: 3 additions & 4 deletions examples/message_demo/src/message_demo.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
use std::convert::TryInto;
use std::env;
use std::sync::Arc;
use std::{convert::TryInto, env, sync::Arc};

use anyhow::{Error, Result};
use rosidl_runtime_rs::{seq, BoundedSequence, Message, Sequence};
Expand Down Expand Up @@ -126,7 +124,8 @@ fn demonstrate_sequences() {
assert_eq!(float_vec_1, float_vec_2);
// Sequences also implement FromIterator.
let mut int_seq_unbounded: Sequence<i32> = [42; 4].into_iter().collect();
// Bounded sequences will ignore remaining items once the length bound is reached
// Bounded sequences will ignore remaining items once the length bound is
// reached
let mut int_seq_bounded: BoundedSequence<i32, 3> = [42; 4].into_iter().collect();
// Sequences deref to slices
int_seq_bounded[2] = 24;
Expand Down
7 changes: 7 additions & 0 deletions examples/minimal_client_service/.rustfmt.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
imports_granularity = "Crate"
array_width = 60
attr_fn_like_width = 70
brace_style = "SameLineWhere"
combine_control_expr = false
comment_width = 80
wrap_comments = true
7 changes: 7 additions & 0 deletions examples/minimal_pub_sub/.rustfmt.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
imports_granularity = "Crate"
array_width = 60
attr_fn_like_width = 70
brace_style = "SameLineWhere"
combine_control_expr = false
comment_width = 80
wrap_comments = true
10 changes: 7 additions & 3 deletions examples/minimal_pub_sub/src/minimal_two_nodes.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
use std::env;
use std::sync::atomic::{AtomicU32, Ordering};
use std::sync::{Arc, Mutex};
use std::{
env,
sync::{
atomic::{AtomicU32, Ordering},
Arc, Mutex,
},
};

use anyhow::{Error, Result};

Expand Down
7 changes: 7 additions & 0 deletions rclrs/.rustfmt.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
imports_granularity = "Crate"
array_width = 60
attr_fn_like_width = 70
brace_style = "SameLineWhere"
combine_control_expr = false
comment_width = 80
wrap_comments = true
20 changes: 12 additions & 8 deletions rclrs/build.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use std::env;
use std::fs::read_dir;
use std::path::{Path, PathBuf};
use std::{
env,
fs::read_dir,
path::{Path, PathBuf},
};

const AMENT_PREFIX_PATH: &str = "AMENT_PREFIX_PATH";
const ROS_DISTRO: &str = "ROS_DISTRO";
Expand Down Expand Up @@ -65,8 +67,9 @@ fn main() {
// #############
//
// For each prefix in ${AMENT_PREFIX_PATH}:
// Search through ament index at ${prefix}/share/ament_index/resource_index/packages/ to find packages to include
// The include root will be located at either:
// Search through ament index at
// ${prefix}/share/ament_index/resource_index/packages/ to find packages to
// include The include root will be located at either:
// - ${prefix}/include/ (old style)
// - ${prefix}/include/${package_name} (new style)
// - ${prefix}/include/CycloneDDS (special case, match for this)
Expand Down Expand Up @@ -97,9 +100,10 @@ fn main() {
if package_include_dir.is_dir() {
let new_style_include_dir = package_include_dir.join(&package);

// CycloneDDS is a special case - it needs to be included as if it were a new-style path, but
// doesn't actually have a secondary folder within it called "CycloneDDS"
// TODO(jhdcs): if this changes in future, remove this check
// CycloneDDS is a special case - it needs to be included as if it were a
// new-style path, but doesn't actually have a secondary folder
// within it called "CycloneDDS" TODO(jhdcs): if this changes in
// future, remove this check
if package == "CycloneDDS" || new_style_include_dir.is_dir() {
builder =
builder.clang_arg(format!("-isystem{}", package_include_dir.display()));
Expand Down
52 changes: 29 additions & 23 deletions rclrs/src/arguments.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
use std::ffi::CString;
use std::os::raw::c_char;
use std::os::raw::c_void;
use std::ptr::null_mut;
use std::{
ffi::CString,
os::raw::{c_char, c_void},
ptr::null_mut,
};

use crate::error::*;
use crate::rcl_bindings::*;
use crate::{error::*, rcl_bindings::*};

/// Extract non-ROS arguments from program's input arguments.
///
/// `args` is expected to be the input arguments of the program (e.g. [`std::env::args()`]),
/// which are expected to contain at least one element - the executable name.
/// `args` is expected to be the input arguments of the program (e.g.
/// [`std::env::args()`]), which are expected to contain at least one element -
/// the executable name.
///
/// ROS arguments are arguments between `--ros-args` and `--`, with the final `--` being optional.
/// Everything else is considered as non-ROS arguments and will be left unparsed by
/// [`Context::new()`][1] etc.
/// Extracted non-ROS arguments are returned in the order that they appear by this function.
/// ROS arguments are arguments between `--ros-args` and `--`, with the final
/// `--` being optional. Everything else is considered as non-ROS arguments and
/// will be left unparsed by [`Context::new()`][1] etc.
/// Extracted non-ROS arguments are returned in the order that they appear by
/// this function.
///
/// # Example
/// ```
Expand Down Expand Up @@ -79,14 +81,16 @@ pub fn extract_non_ros_args(
ret
}

/// Returns arguments type held by `rcl_arguments` basing on `rcl_get_count` and `rcl_get_indices` function pointers.
/// Returns arguments type held by `rcl_arguments` basing on `rcl_get_count` and
/// `rcl_get_indices` function pointers.
///
/// This function must be called after `rcl_arguments` was initialized. `args` must be array of input arguments passed to node/program.
/// This function must be called after `rcl_arguments` was initialized. `args`
/// must be array of input arguments passed to node/program.
///
/// SAFETY: `rcl_get_count` and `rcl_get_indices` has to be corresponding rcl API functions, e.g.:
/// `rcl_arguments_get_count_unparsed` -> `rcl_arguments_get_unparsed`
/// `rcl_arguments_get_count_unparsed_ros` -> `rcl_arguments_get_count_ros`
/// ...
/// SAFETY: `rcl_get_count` and `rcl_get_indices` has to be corresponding rcl
/// API functions, e.g.: `rcl_arguments_get_count_unparsed` ->
/// `rcl_arguments_get_unparsed` `rcl_arguments_get_count_unparsed_ros` ->
/// `rcl_arguments_get_count_ros` ...
pub(crate) fn get_rcl_arguments(
rcl_get_count: unsafe extern "C" fn(*const rcl_arguments_t) -> std::os::raw::c_int,
rcl_get_indices: unsafe extern "C" fn(
Expand All @@ -110,13 +114,14 @@ pub(crate) fn get_rcl_arguments(
unsafe {
// SAFETY: No preconditions for this function.
let allocator = rcutils_get_default_allocator();
// SAFETY: The indices_ptr is an output parameter, so it is expected that it contains null.
// The indices_ptr will need to be freed by the caller, which happens later in this function.
// SAFETY: The indices_ptr is an output parameter, so it is expected that it
// contains null. The indices_ptr will need to be freed by the caller,
// which happens later in this function.
rcl_get_indices(rcl_arguments, allocator, &mut indices_ptr).ok()?;

for i in 0..args_count {
// SAFETY: rcl_get_indices finished with success and rcl_get_count is matching function
// according to documentation of this function
// SAFETY: rcl_get_indices finished with success and rcl_get_count is matching
// function according to documentation of this function
let index = *(indices_ptr.add(i));
// SAFETY: rcl_get_indices and rcl_get_count are matching functions according
// to documentation of this function
Expand All @@ -137,7 +142,8 @@ mod tests {

#[test]
fn test_non_ros_arguments() -> Result<(), String> {
// ROS args are expected to be between '--ros-args' and '--'. Everything beside that is 'non-ROS'.
// ROS args are expected to be between '--ros-args' and '--'. Everything beside
// that is 'non-ROS'.
let input_args: [String; 6] = [
"non-ros1",
"--ros-args",
Expand Down
80 changes: 46 additions & 34 deletions rclrs/src/client.rs
Original file line number Diff line number Diff line change
@@ -1,23 +1,27 @@
use std::boxed::Box;
use std::collections::HashMap;
use std::ffi::CString;
use std::sync::atomic::AtomicBool;
use std::sync::{Arc, Mutex, MutexGuard};
use std::{
boxed::Box,
collections::HashMap,
ffi::CString,
sync::{atomic::AtomicBool, Arc, Mutex, MutexGuard},
};

use futures::channel::oneshot;
use rosidl_runtime_rs::Message;

use crate::error::{RclReturnCode, ToResult};
use crate::MessageCow;
use crate::{rcl_bindings::*, NodeHandle, RclrsError, ENTITY_LIFECYCLE_MUTEX};
use crate::{
error::{RclReturnCode, ToResult},
rcl_bindings::*,
MessageCow, NodeHandle, RclrsError, ENTITY_LIFECYCLE_MUTEX,
};

// SAFETY: The functions accessing this type, including drop(), shouldn't care about the thread
// they are running in. Therefore, this type can be safely sent to another thread.
// SAFETY: The functions accessing this type, including drop(), shouldn't care
// about the thread they are running in. Therefore, this type can be safely sent
// to another thread.
unsafe impl Send for rcl_client_t {}

/// Manage the lifecycle of an `rcl_client_t`, including managing its dependencies
/// on `rcl_node_t` and `rcl_context_t` by ensuring that these dependencies are
/// [dropped after][1] the `rcl_client_t`.
/// Manage the lifecycle of an `rcl_client_t`, including managing its
/// dependencies on `rcl_node_t` and `rcl_context_t` by ensuring that these
/// dependencies are [dropped after][1] the `rcl_client_t`.
///
/// [1]: <https://doc.rust-lang.org/reference/destructors.html>
pub struct ClientHandle {
Expand All @@ -38,7 +42,8 @@ impl Drop for ClientHandle {
let mut rcl_node = self.node_handle.rcl_node.lock().unwrap();
let _lifecycle_lock = ENTITY_LIFECYCLE_MUTEX.lock().unwrap();
// SAFETY: The entity lifecycle mutex is locked to protect against the risk of
// global variables in the rmw implementation being unsafely modified during cleanup.
// global variables in the rmw implementation being unsafely modified during
// cleanup.
unsafe {
rcl_client_fini(rcl_client, &mut *rcl_node);
}
Expand All @@ -61,8 +66,9 @@ type RequestId = i64;

/// Main class responsible for sending requests to a ROS service.
///
/// The only available way to instantiate clients is via [`Node::create_client`][1], this is to
/// ensure that [`Node`][2]s can track all the clients that have been created.
/// The only available way to instantiate clients is via
/// [`Node::create_client`][1], this is to ensure that [`Node`][2]s can track
/// all the clients that have been created.
///
/// [1]: crate::Node::create_client
/// [2]: crate::Node
Expand Down Expand Up @@ -104,11 +110,13 @@ where

// SAFETY:
// * The rcl_client was zero-initialized as expected by this function.
// * The rcl_node is kept alive by the NodeHandle because it is a dependency of the client.
// * The topic name and the options are copied by this function, so they can be dropped
// afterwards.
// * The rcl_node is kept alive by the NodeHandle because it is a dependency of
// the client.
// * The topic name and the options are copied by this function, so they can be
// dropped afterwards.
// * The entity lifecycle mutex is locked to protect against the risk of global
// variables in the rmw implementation being unsafely modified during initialization.
// variables in the rmw implementation being unsafely modified during
// initialization.
unsafe {
rcl_client_init(
&mut rcl_client,
Expand Down Expand Up @@ -141,13 +149,14 @@ where
/// The [`MessageCow`] trait is implemented by any
/// [`Message`] as well as any reference to a `Message`.
///
/// The reason for allowing owned messages is that publishing owned messages can be more
/// efficient in the case of idiomatic messages[^note].
/// The reason for allowing owned messages is that publishing owned messages
/// can be more efficient in the case of idiomatic messages[^note].
///
/// [^note]: See the [`Message`] trait for an explanation of "idiomatic".
///
/// Hence, when a message will not be needed anymore after publishing, pass it by value.
/// When a message will be needed again after publishing, pass it by reference, instead of cloning and passing by value.
/// Hence, when a message will not be needed anymore after publishing, pass
/// it by value. When a message will be needed again after publishing,
/// pass it by reference, instead of cloning and passing by value.
pub fn async_send_request_with_callback<'a, M: MessageCow<'a, T::Request>, F>(
&self,
message: M,
Expand All @@ -159,7 +168,8 @@ where
let rmw_message = T::Request::into_rmw_message(message.into_cow());
let mut sequence_number = -1;
unsafe {
// SAFETY: The request type is guaranteed to match the client type by the type system.
// SAFETY: The request type is guaranteed to match the client type by the type
// system.
rcl_send_request(
&*self.handle.lock() as *const _,
rmw_message.as_ref() as *const <T::Request as Message>::RmwMsg as *mut _,
Expand All @@ -177,13 +187,14 @@ where
/// The [`MessageCow`] trait is implemented by any
/// [`Message`] as well as any reference to a `Message`.
///
/// The reason for allowing owned messages is that publishing owned messages can be more
/// efficient in the case of idiomatic messages[^note].
/// The reason for allowing owned messages is that publishing owned messages
/// can be more efficient in the case of idiomatic messages[^note].
///
/// [^note]: See the [`Message`] trait for an explanation of "idiomatic".
///
/// Hence, when a message will not be needed anymore after publishing, pass it by value.
/// When a message will be needed again after publishing, pass it by reference, instead of cloning and passing by value.
/// Hence, when a message will not be needed anymore after publishing, pass
/// it by value. When a message will be needed again after publishing,
/// pass it by reference, instead of cloning and passing by value.
pub async fn call_async<'a, R: MessageCow<'a, T::Request>>(
&self,
request: R,
Expand All @@ -194,7 +205,8 @@ where
let rmw_message = T::Request::into_rmw_message(request.into_cow());
let mut sequence_number = -1;
unsafe {
// SAFETY: The request type is guaranteed to match the client type by the type system.
// SAFETY: The request type is guaranteed to match the client type by the type
// system.
rcl_send_request(
&*self.handle.lock() as *const _,
rmw_message.as_ref() as *const <T::Request as Message>::RmwMsg as *mut _,
Expand All @@ -204,8 +216,8 @@ where
.ok()?;
let (tx, rx) = oneshot::channel::<T::Response>();
self.futures.lock().unwrap().insert(sequence_number, tx);
// It is safe to call unwrap() here since the `Canceled` error will only happen when the
// `Sender` is dropped
// It is safe to call unwrap() here since the `Canceled` error will only happen
// when the `Sender` is dropped
// https://docs.rs/futures/latest/futures/channel/oneshot/struct.Canceled.html
Ok(rx.await.unwrap())
}
Expand Down Expand Up @@ -255,8 +267,8 @@ where

/// Check if a service server is available.
///
/// Will return true if there is a service server available, false if unavailable.
///
/// Will return true if there is a service server available, false if
/// unavailable.
pub fn service_is_ready(&self) -> Result<bool, RclrsError> {
let mut is_ready = false;
let client = &mut *self.handle.rcl_client.lock().unwrap();
Expand Down
Loading