Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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: 6 additions & 1 deletion .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,15 @@ jobs:
use-ros2-testing: ${{ matrix.ros_distribution == 'rolling' }}

- name: Setup Rust
uses: dtolnay/rust-toolchain@1.74.0
uses: dtolnay/rust-toolchain@1.78.0
with:
components: clippy, rustfmt

- name: Set Rust backtrace
run: |
echo "RUST_BACKTRACE=1" >> $GITHUB_ENV


- name: Install colcon-cargo and colcon-ros-cargo
run: |
sudo pip3 install git+https://github.com/colcon/colcon-cargo.git
Expand Down
2 changes: 1 addition & 1 deletion rclrs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ authors = ["Esteve Fernandez <[email protected]>", "Nikolai Morin <nnmmgit@gmail
edition = "2021"
license = "Apache-2.0"
description = "A ROS 2 client library for developing robotics applications in Rust"
rust-version = "1.63"
rust-version = "1.78"

[lib]
path = "src/lib.rs"
Expand Down
60 changes: 32 additions & 28 deletions rclrs/src/node/graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -419,38 +419,42 @@ fn convert_names_and_types(
rcl_names_and_types: rmw_names_and_types_t,
) -> HashMap<String, Vec<String>> {
let mut names_and_types: TopicNamesAndTypes = HashMap::new();

// SAFETY: Safe if the rcl_names_and_types arg has been initialized by the caller
let name_slice = unsafe {
slice::from_raw_parts(
rcl_names_and_types.names.data,
rcl_names_and_types.names.size,
)
};

for (idx, name) in name_slice.iter().enumerate() {
// SAFETY: The slice contains valid C string pointers if it was populated by the caller
let name: String = unsafe {
let cstr = CStr::from_ptr(*name);
cstr.to_string_lossy().into_owned()
// Check if the names.data pointer is not null
if rcl_names_and_types.names.data.is_null() {
panic!("Invalid names.data pointer");
} else {
// SAFETY: Safe if the rcl_names_and_types arg has been initialized by the caller
let name_slice = unsafe {
slice::from_raw_parts(
rcl_names_and_types.names.data,
rcl_names_and_types.names.size,
)
};

// SAFETY: Safe as long as rcl_names_and_types was populated by the caller
let types: Vec<String> = unsafe {
let p = rcl_names_and_types.types.add(idx);
slice::from_raw_parts((*p).data, (*p).size)
.iter()
.map(|s| {
let cstr = CStr::from_ptr(*s);
cstr.to_string_lossy().into_owned()
})
.collect()
};
for (idx, name) in name_slice.iter().enumerate() {
// SAFETY: The slice contains valid C string pointers if it was populated by the caller
let name: String = unsafe {
let cstr = CStr::from_ptr(*name);
cstr.to_string_lossy().into_owned()
};

// SAFETY: Safe as long as rcl_names_and_types was populated by the caller
let types: Vec<String> = unsafe {
let p = rcl_names_and_types.types.add(idx);
slice::from_raw_parts((*p).data, (*p).size)
.iter()
.map(|s| {
let cstr = CStr::from_ptr(*s);
cstr.to_string_lossy().into_owned()
})
.collect()
};

names_and_types.insert(name, types);
}

names_and_types.insert(name, types);
names_and_types
}

names_and_types
}

#[cfg(test)]
Expand Down
4 changes: 2 additions & 2 deletions rclrs/src/parameter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -668,9 +668,9 @@ impl<'a> Parameters<'a> {
/// Returns:
/// * `Ok(())` if setting was successful.
/// * [`Err(DeclarationError::TypeMismatch)`] if the type of the requested value is different
/// from the parameter's type.
/// from the parameter's type.
/// * [`Err(DeclarationError::OutOfRange)`] if the requested value is out of the parameter's
/// range.
/// range.
/// * [`Err(DeclarationError::ReadOnly)`] if the parameter is read only.
pub fn set<T: ParameterVariant>(
&self,
Expand Down
2 changes: 1 addition & 1 deletion rclrs/src/parameter/range.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ impl From<()> for ParameterRanges {
/// Usually only one of these ranges will be applied, but all have to be stored since:
///
/// * A dynamic parameter can change its type at runtime, in which case a different range could be
/// applied.
/// applied.
/// * Introspection through service calls requires all the ranges to be reported to the user.
#[derive(Clone, Debug, Default)]
pub struct ParameterRanges {
Expand Down
5 changes: 3 additions & 2 deletions rclrs/src/subscription.rs
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ where
fn execute(&self) -> Result<(), RclrsError> {
// Immediately evaluated closure, to handle SubscriptionTakeFailed
// outside this match
match (|| {
let closure_result = || {
match &mut *self.callback.lock().unwrap() {
AnySubscriptionCallback::Regular(cb) => {
let (msg, _) = self.take()?;
Expand Down Expand Up @@ -302,7 +302,8 @@ where
}
}
Ok(())
})() {
};
match closure_result() {
Err(RclrsError::RclError {
code: RclReturnCode::SubscriptionTakeFailed,
..
Expand Down
30 changes: 15 additions & 15 deletions rclrs/src/subscription/message_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,23 @@ use crate::rcl_bindings::*;
/// To quote the `rmw` documentation:
///
/// > The identifier uniquely identifies the publisher for the local context, but
/// it will not necessarily be the same identifier given in other contexts or processes
/// for the same publisher.
/// Therefore the identifier will uniquely identify the publisher within your application
/// but may disagree about the identifier for that publisher when compared to another
/// application.
/// Even with this limitation, when combined with the publisher sequence number it can
/// uniquely identify a message within your local context.
/// Publisher GIDs generated by the RMW implementation could collide at some point, in which
/// case it is not possible to distinguish which publisher sent the message.
/// The details of how GIDs are generated are RMW implementation dependent.
/// > it will not necessarily be the same identifier given in other contexts or processes
/// > for the same publisher.
/// > Therefore the identifier will uniquely identify the publisher within your application
/// > but may disagree about the identifier for that publisher when compared to another
/// > application.
/// > Even with this limitation, when combined with the publisher sequence number it can
/// > uniquely identify a message within your local context.
/// > Publisher GIDs generated by the RMW implementation could collide at some point, in which
/// > case it is not possible to distinguish which publisher sent the message.
/// > The details of how GIDs are generated are RMW implementation dependent.
///
/// > It is possible the the RMW implementation needs to reuse a publisher GID,
/// due to running out of unique identifiers or some other constraint, in which case
/// the RMW implementation may document what happens in that case, but that
/// behavior is not defined here.
/// However, this should be avoided, if at all possible, by the RMW implementation,
/// and should be unlikely to happen in practice.
/// > due to running out of unique identifiers or some other constraint, in which case
/// > the RMW implementation may document what happens in that case, but that
/// > behavior is not defined here.
/// > However, this should be avoided, if at all possible, by the RMW implementation,
/// > and should be unlikely to happen in practice.
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct PublisherGid {
/// Bytes identifying a publisher in the RMW implementation.
Expand Down
2 changes: 1 addition & 1 deletion rclrs/src/wait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,7 @@ impl WaitSet {
///
/// - Passing a wait set with no wait-able items in it will return an error.
/// - The timeout must not be so large so as to overflow an `i64` with its nanosecond
/// representation, or an error will occur.
/// representation, or an error will occur.
///
/// This list is not comprehensive, since further errors may occur in the `rmw` or `rcl` layers.
///
Expand Down