Skip to content

Commit ad9667f

Browse files
authored
Wrap slice::from_raw_parts to be compatible with rcl (#419)
* Wrap slice::from_raw_parts to be compatible with rcl Signed-off-by: Michael X. Grey <[email protected]> * Fix style Signed-off-by: Michael X. Grey <[email protected]> --------- Signed-off-by: Michael X. Grey <[email protected]>
1 parent 5903d73 commit ad9667f

File tree

4 files changed

+40
-27
lines changed

4 files changed

+40
-27
lines changed

rclrs/src/node/graph.rs

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
use std::{
22
collections::HashMap,
33
ffi::{CStr, CString},
4-
slice,
54
};
65

76
use crate::{rcl_bindings::*, Node, RclrsError, ToResult};
@@ -182,8 +181,8 @@ impl Node {
182181
// namespaces are populated with valid data
183182
let (names_slice, namespaces_slice) = unsafe {
184183
(
185-
slice::from_raw_parts(rcl_names.data, rcl_names.size),
186-
slice::from_raw_parts(rcl_namespaces.data, rcl_namespaces.size),
184+
rcl_from_raw_parts(rcl_names.data, rcl_names.size),
185+
rcl_from_raw_parts(rcl_namespaces.data, rcl_namespaces.size),
187186
)
188187
};
189188

@@ -230,9 +229,9 @@ impl Node {
230229
// SAFETY: The previous function successfully returned, so the arrays are valid
231230
let (names_slice, namespaces_slice, enclaves_slice) = unsafe {
232231
(
233-
slice::from_raw_parts(rcl_names.data, rcl_names.size),
234-
slice::from_raw_parts(rcl_namespaces.data, rcl_namespaces.size),
235-
slice::from_raw_parts(rcl_enclaves.data, rcl_enclaves.size),
232+
rcl_from_raw_parts(rcl_names.data, rcl_names.size),
233+
rcl_from_raw_parts(rcl_namespaces.data, rcl_namespaces.size),
234+
rcl_from_raw_parts(rcl_enclaves.data, rcl_enclaves.size),
236235
)
237236
};
238237

@@ -379,10 +378,9 @@ impl Node {
379378
.ok()?;
380379
}
381380

382-
// SAFETY: The previous call returned successfully, so the slice is valid
383-
let topic_endpoint_infos_slice = unsafe {
384-
slice::from_raw_parts(rcl_publishers_info.info_array, rcl_publishers_info.size)
385-
};
381+
// SAFETY: The previous call returned successfully, so the data is valid
382+
let topic_endpoint_infos_slice =
383+
unsafe { rcl_from_raw_parts(rcl_publishers_info.info_array, rcl_publishers_info.size) };
386384

387385
// SAFETY: Because the rcl call returned successfully, each element of the slice points
388386
// to a valid topic_endpoint_info object, which contains valid C strings
@@ -422,7 +420,7 @@ fn convert_names_and_types(
422420

423421
// SAFETY: Safe if the rcl_names_and_types arg has been initialized by the caller
424422
let name_slice = unsafe {
425-
slice::from_raw_parts(
423+
rcl_from_raw_parts(
426424
rcl_names_and_types.names.data,
427425
rcl_names_and_types.names.size,
428426
)
@@ -438,7 +436,7 @@ fn convert_names_and_types(
438436
// SAFETY: Safe as long as rcl_names_and_types was populated by the caller
439437
let types: Vec<String> = unsafe {
440438
let p = rcl_names_and_types.types.add(idx);
441-
slice::from_raw_parts((*p).data, (*p).size)
439+
rcl_from_raw_parts((*p).data, (*p).size)
442440
.iter()
443441
.map(|s| {
444442
let cstr = CStr::from_ptr(*s);

rclrs/src/parameter/override_map.rs

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,8 @@ impl RclParamsIter<'_> {
4949
}
5050
} else {
5151
let node_name_ptrs =
52-
std::slice::from_raw_parts((*rcl_params).node_names, (*rcl_params).num_nodes);
53-
let rcl_node_params =
54-
std::slice::from_raw_parts((*rcl_params).params, (*rcl_params).num_nodes);
52+
rcl_from_raw_parts((*rcl_params).node_names, (*rcl_params).num_nodes);
53+
let rcl_node_params = rcl_from_raw_parts((*rcl_params).params, (*rcl_params).num_nodes);
5554
Self {
5655
node_name_ptrs,
5756
rcl_node_params,
@@ -83,11 +82,9 @@ impl<'a> RclNodeParamsIter<'a> {
8382
// sizes or dangling pointers.
8483
pub unsafe fn new(rcl_node_params: &'a rcl_node_params_t) -> Self {
8584
let param_name_ptrs =
86-
std::slice::from_raw_parts(rcl_node_params.parameter_names, rcl_node_params.num_params);
87-
let rcl_variants = std::slice::from_raw_parts(
88-
rcl_node_params.parameter_values,
89-
rcl_node_params.num_params,
90-
);
85+
rcl_from_raw_parts(rcl_node_params.parameter_names, rcl_node_params.num_params);
86+
let rcl_variants =
87+
rcl_from_raw_parts(rcl_node_params.parameter_values, rcl_node_params.num_params);
9188
Self {
9289
param_name_ptrs,
9390
rcl_variants,

rclrs/src/parameter/value.rs

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -460,25 +460,23 @@ impl ParameterValue {
460460
ParameterValue::String(s.into())
461461
} else if !var.byte_array_value.is_null() {
462462
let rcl_byte_array = &*var.byte_array_value;
463-
let slice = std::slice::from_raw_parts(rcl_byte_array.values, rcl_byte_array.size);
463+
let slice = rcl_from_raw_parts(rcl_byte_array.values, rcl_byte_array.size);
464464
ParameterValue::ByteArray(slice.into())
465465
} else if !var.bool_array_value.is_null() {
466466
let rcl_bool_array = &*var.bool_array_value;
467-
let slice = std::slice::from_raw_parts(rcl_bool_array.values, rcl_bool_array.size);
467+
let slice = rcl_from_raw_parts(rcl_bool_array.values, rcl_bool_array.size);
468468
ParameterValue::BoolArray(slice.into())
469469
} else if !var.integer_array_value.is_null() {
470470
let rcl_integer_array = &*var.integer_array_value;
471-
let slice =
472-
std::slice::from_raw_parts(rcl_integer_array.values, rcl_integer_array.size);
471+
let slice = rcl_from_raw_parts(rcl_integer_array.values, rcl_integer_array.size);
473472
ParameterValue::IntegerArray(slice.into())
474473
} else if !var.double_array_value.is_null() {
475474
let rcl_double_array = &*var.double_array_value;
476-
let slice = std::slice::from_raw_parts(rcl_double_array.values, rcl_double_array.size);
475+
let slice = rcl_from_raw_parts(rcl_double_array.values, rcl_double_array.size);
477476
ParameterValue::DoubleArray(slice.into())
478477
} else if !var.string_array_value.is_null() {
479478
let rcutils_string_array = &*var.string_array_value;
480-
let slice =
481-
std::slice::from_raw_parts(rcutils_string_array.data, rcutils_string_array.size);
479+
let slice = rcl_from_raw_parts(rcutils_string_array.data, rcutils_string_array.size);
482480
let strings = slice
483481
.iter()
484482
.map(|&ptr| {

rclrs/src/rcl_bindings.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,3 +148,23 @@ cfg_if::cfg_if! {
148148
pub const RMW_GID_STORAGE_SIZE: usize = rmw_gid_storage_size_constant;
149149
}
150150
}
151+
152+
/// Wrapper around [`std::slice::from_raw_parts`] that accommodates the rcl
153+
/// convention of providing a null pointer to represent empty arrays. This
154+
/// violates the safety requirements of [`std::slice::from_raw_parts`].
155+
///
156+
/// # Safety
157+
///
158+
/// Behavior is undefined in all the same scenarios as [`slice::from_raw_parts`]
159+
/// (see its safety section) except that null pointers are allowed and will
160+
/// return a slice to an empty array.
161+
pub(crate) unsafe fn rcl_from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] {
162+
if data.is_null() {
163+
&[]
164+
} else {
165+
// SAFETY: The user of this function is instructed to abide by all the
166+
// safety requirements of slice::from_raw_parts except for null pointer
167+
// values, which are checked above.
168+
unsafe { std::slice::from_raw_parts(data, len) }
169+
}
170+
}

0 commit comments

Comments
 (0)