diff --git a/r2r/src/msg_types.rs b/r2r/src/msg_types.rs index ab2d0bf..524dff0 100644 --- a/r2r/src/msg_types.rs +++ b/r2r/src/msg_types.rs @@ -93,8 +93,12 @@ pub trait WrappedTypesupport: ) }; - let data_bytes = unsafe { - std::slice::from_raw_parts(msg_buf.buffer, msg_buf.buffer_length).to_vec() + let data_bytes = if msg_buf.buffer == std::ptr::null_mut() { + Vec::new() + } else { + unsafe { + std::slice::from_raw_parts(msg_buf.buffer, msg_buf.buffer_length).to_vec() + } }; Self::destroy_msg(msg); diff --git a/r2r/src/nodes.rs b/r2r/src/nodes.rs index 03830b1..c458c2c 100644 --- a/r2r/src/nodes.rs +++ b/r2r/src/nodes.rs @@ -115,6 +115,15 @@ impl Node { return Ok(()); } + unsafe { + if (*(*params.as_ref())).node_names == std::ptr::null_mut() + || (*(*params.as_ref())).params == std::ptr::null_mut() + { + rcl_yaml_node_struct_fini(*params); + return Ok(()); + } + } + let node_names = unsafe { std::slice::from_raw_parts( (*(*params.as_ref())).node_names, @@ -148,18 +157,22 @@ impl Node { } // make key value pairs. - let param_names = - unsafe { std::slice::from_raw_parts(np.parameter_names, np.num_params) }; - - let param_values = - unsafe { std::slice::from_raw_parts(np.parameter_values, np.num_params) }; - let mut params = self.params.lock().unwrap(); - for (s, v) in param_names.iter().zip(param_values) { - let s = unsafe { CStr::from_ptr(*s) }; - let key = s.to_str().unwrap_or(""); - let val = ParameterValue::from_rcl(v); - params.insert(key.to_owned(), Parameter::new(val)); + if np.parameter_names != std::ptr::null_mut() + && np.parameter_values != std::ptr::null_mut() + { + let param_names = + unsafe { std::slice::from_raw_parts(np.parameter_names, np.num_params) }; + + let param_values = + unsafe { std::slice::from_raw_parts(np.parameter_values, np.num_params) }; + + for (s, v) in param_names.iter().zip(param_values) { + let s = unsafe { CStr::from_ptr(*s) }; + let key = s.to_str().unwrap_or(""); + let val = ParameterValue::from_rcl(v); + params.insert(key.to_owned(), Parameter::new(val)); + } } } @@ -1028,29 +1041,33 @@ impl Node { return; } - let ws_subs = - unsafe { std::slice::from_raw_parts(ws.subscriptions, self.subscribers.len()) }; let mut subs_to_remove = vec![]; - for (s, ws_s) in self.subscribers.iter_mut().zip(ws_subs) { - if ws_s != &std::ptr::null() { - let dropped = s.handle_incoming(); - if dropped { - s.destroy(&mut self.node_handle); - subs_to_remove.push(*s.handle()); + if ws.subscriptions != std::ptr::null_mut() { + let ws_subs = + unsafe { std::slice::from_raw_parts(ws.subscriptions, self.subscribers.len()) }; + for (s, ws_s) in self.subscribers.iter_mut().zip(ws_subs) { + if ws_s != &std::ptr::null() { + let dropped = s.handle_incoming(); + if dropped { + s.destroy(&mut self.node_handle); + subs_to_remove.push(*s.handle()); + } } } } self.subscribers .retain(|s| !subs_to_remove.contains(s.handle())); - let ws_timers = unsafe { std::slice::from_raw_parts(ws.timers, self.timers.len()) }; let mut timers_to_remove = vec![]; - for (s, ws_s) in self.timers.iter_mut().zip(ws_timers) { - if ws_s != &std::ptr::null() { - // TODO: move this to impl Timer - let dropped = s.handle_incoming(); - if dropped { - timers_to_remove.push((*s.timer_handle).to_owned()); + if ws.timers != std::ptr::null_mut() { + let ws_timers = unsafe { std::slice::from_raw_parts(ws.timers, self.timers.len()) }; + for (s, ws_s) in self.timers.iter_mut().zip(ws_timers) { + if ws_s != &std::ptr::null() { + // TODO: move this to impl Timer + let dropped = s.handle_incoming(); + if dropped { + timers_to_remove.push((*s.timer_handle).to_owned()); + } } } } @@ -1058,23 +1075,28 @@ impl Node { self.timers .retain(|t| !timers_to_remove.contains(&*t.timer_handle)); - let ws_clients = unsafe { std::slice::from_raw_parts(ws.clients, self.clients.len()) }; - for (s, ws_s) in self.clients.iter_mut().zip(ws_clients) { - if ws_s != &std::ptr::null() { - let mut s = s.lock().unwrap(); - s.handle_response(); + if ws.clients != std::ptr::null_mut() { + let ws_clients = unsafe { std::slice::from_raw_parts(ws.clients, self.clients.len()) }; + for (s, ws_s) in self.clients.iter_mut().zip(ws_clients) { + if ws_s != &std::ptr::null() { + let mut s = s.lock().unwrap(); + s.handle_response(); + } } } - let ws_services = unsafe { std::slice::from_raw_parts(ws.services, self.services.len()) }; let mut services_to_remove = vec![]; - for (s, ws_s) in self.services.iter_mut().zip(ws_services) { - if ws_s != &std::ptr::null() { - let mut service = s.lock().unwrap(); - let dropped = service.handle_request(s.clone()); - if dropped { - service.destroy(&mut self.node_handle); - services_to_remove.push(*service.handle()); + if ws.services != std::ptr::null_mut() { + let ws_services = + unsafe { std::slice::from_raw_parts(ws.services, self.services.len()) }; + for (s, ws_s) in self.services.iter_mut().zip(ws_services) { + if ws_s != &std::ptr::null() { + let mut service = s.lock().unwrap(); + let dropped = service.handle_request(s.clone()); + if dropped { + service.destroy(&mut self.node_handle); + services_to_remove.push(*service.handle()); + } } } } @@ -1194,20 +1216,22 @@ impl Node { return Err(Error::from_rcl_error(ret)); } - let names = unsafe { std::slice::from_raw_parts(tnat.names.data, tnat.names.size) }; - let types = unsafe { std::slice::from_raw_parts(tnat.types, tnat.names.size) }; - let mut res = HashMap::new(); - for (n, t) in names.iter().zip(types) { - let topic_name = unsafe { CStr::from_ptr(*n).to_str().unwrap().to_owned() }; - let topic_types = unsafe { std::slice::from_raw_parts(t, t.size) }; - let topic_types: Vec = unsafe { - topic_types - .iter() - .map(|t| CStr::from_ptr(*(t.data)).to_str().unwrap().to_owned()) - .collect() - }; - res.insert(topic_name, topic_types); + if tnat.names.data != std::ptr::null_mut() && tnat.types != std::ptr::null_mut() { + let names = unsafe { std::slice::from_raw_parts(tnat.names.data, tnat.names.size) }; + let types = unsafe { std::slice::from_raw_parts(tnat.types, tnat.names.size) }; + + for (n, t) in names.iter().zip(types) { + let topic_name = unsafe { CStr::from_ptr(*n).to_str().unwrap().to_owned() }; + let topic_types = unsafe { std::slice::from_raw_parts(t, t.size) }; + let topic_types: Vec = unsafe { + topic_types + .iter() + .map(|t| CStr::from_ptr(*(t.data)).to_str().unwrap().to_owned()) + .collect() + }; + res.insert(topic_name, topic_types); + } } unsafe { rmw_names_and_types_fini(&mut tnat); @@ -1532,11 +1556,13 @@ fn convert_info_array_to_vec( ) -> Vec { let mut topic_info_list = Vec::with_capacity(info_array.size); - unsafe { - let infos = std::slice::from_raw_parts(info_array.info_array, info_array.size); - for &info in infos { - let endpoint_info = TopicEndpointInfo::from(info); - topic_info_list.push(endpoint_info); + if info_array.info_array != std::ptr::null_mut() { + unsafe { + let infos = std::slice::from_raw_parts(info_array.info_array, info_array.size); + for &info in infos { + let endpoint_info = TopicEndpointInfo::from(info); + topic_info_list.push(endpoint_info); + } } } diff --git a/r2r/src/parameters.rs b/r2r/src/parameters.rs index 8cc80e8..5648f1e 100644 --- a/r2r/src/parameters.rs +++ b/r2r/src/parameters.rs @@ -34,36 +34,62 @@ impl ParameterValue { ParameterValue::String(string) } else if !v.byte_array_value.is_null() { let vals = unsafe { - std::slice::from_raw_parts((*v.byte_array_value).values, (*v.byte_array_value).size) + if (*v.byte_array_value).values == std::ptr::null_mut() { + &[] + } else { + std::slice::from_raw_parts( + (*v.byte_array_value).values, + (*v.byte_array_value).size, + ) + } }; ParameterValue::ByteArray(vals.to_vec()) } else if !v.bool_array_value.is_null() { let vals = unsafe { - std::slice::from_raw_parts((*v.bool_array_value).values, (*v.bool_array_value).size) + if (*v.bool_array_value).values == std::ptr::null_mut() { + &[] + } else { + std::slice::from_raw_parts( + (*v.bool_array_value).values, + (*v.bool_array_value).size, + ) + } }; ParameterValue::BoolArray(vals.to_vec()) } else if !v.integer_array_value.is_null() { let vals = unsafe { - std::slice::from_raw_parts( - (*v.integer_array_value).values, - (*v.integer_array_value).size, - ) + if (*v.integer_array_value).values == std::ptr::null_mut() { + &[] + } else { + std::slice::from_raw_parts( + (*v.integer_array_value).values, + (*v.integer_array_value).size, + ) + } }; ParameterValue::IntegerArray(vals.to_vec()) } else if !v.double_array_value.is_null() { let vals = unsafe { - std::slice::from_raw_parts( - (*v.double_array_value).values, - (*v.double_array_value).size, - ) + if (*v.double_array_value).values == std::ptr::null_mut() { + &[] + } else { + std::slice::from_raw_parts( + (*v.double_array_value).values, + (*v.double_array_value).size, + ) + } }; ParameterValue::DoubleArray(vals.to_vec()) } else if !v.string_array_value.is_null() { let vals = unsafe { - std::slice::from_raw_parts( - (*v.string_array_value).data, - (*v.string_array_value).size, - ) + if (*v.string_array_value).data == std::ptr::null_mut() { + &[] + } else { + std::slice::from_raw_parts( + (*v.string_array_value).data, + (*v.string_array_value).size, + ) + } }; let s = vals .iter() diff --git a/r2r/src/subscribers.rs b/r2r/src/subscribers.rs index 1372278..0d3f34f 100644 --- a/r2r/src/subscribers.rs +++ b/r2r/src/subscribers.rs @@ -203,8 +203,12 @@ impl Subscriber_ for RawSubscriber { return false; } - let data_bytes = unsafe { - std::slice::from_raw_parts(self.msg_buf.buffer, self.msg_buf.buffer_length).to_vec() + let data_bytes = if self.msg_buf.buffer == std::ptr::null_mut() { + Vec::new() + } else { + unsafe { + std::slice::from_raw_parts(self.msg_buf.buffer, self.msg_buf.buffer_length).to_vec() + } }; if let Err(e) = self.sender.try_send(data_bytes) { diff --git a/r2r_msg_gen/src/lib.rs b/r2r_msg_gen/src/lib.rs index bc2db19..dc8ba2b 100644 --- a/r2r_msg_gen/src/lib.rs +++ b/r2r_msg_gen/src/lib.rs @@ -446,14 +446,16 @@ pub fn generate_rust_msg(module_: &str, prefix_: &str, name_: &str) -> proc_macr quote! { #field_name : { let mut temp = Vec::with_capacity(msg. #field_name .size); - let slice = unsafe { - std::slice::from_raw_parts( - msg. #field_name .data, - msg. #field_name .size - ) - }; - for s in slice { - temp.push( #module :: #prefix :: #name :: from_native(s)); + if msg. #field_name .data != std::ptr::null_mut() { + let slice = unsafe { + std::slice::from_raw_parts( + msg. #field_name .data, + msg. #field_name .size + ) + }; + for s in slice { + temp.push( #module :: #prefix :: #name :: from_native(s)); + } } temp }, @@ -589,9 +591,11 @@ pub fn generate_rust_msg(module_: &str, prefix_: &str, name_: &str) -> proc_macr #fini_func (&mut msg. #field_name); #init_func (&mut msg. #field_name , self. #field_name .len()); - let slice = std::slice::from_raw_parts_mut(msg. #field_name .data, msg. #field_name .size); - for (t, s) in slice.iter_mut().zip(&self. #field_name ) { - s.copy_to_native(t); + if msg. #field_name .data != std::ptr::null_mut() { + let slice = std::slice::from_raw_parts_mut(msg. #field_name .data, msg. #field_name .size); + for (t, s) in slice.iter_mut().zip(&self. #field_name ) { + s.copy_to_native(t); + } } } } diff --git a/r2r_rcl/src/lib.rs b/r2r_rcl/src/lib.rs index 5a20085..54eb135 100644 --- a/r2r_rcl/src/lib.rs +++ b/r2r_rcl/src/lib.rs @@ -56,13 +56,18 @@ impl rosidl_runtime_c__U16String__Sequence { unsafe { rosidl_runtime_c__U16String__Sequence__init(self as *mut _, values.len()); } - let strs = unsafe { std::slice::from_raw_parts_mut(self.data, values.len()) }; - for (target, source) in strs.iter_mut().zip(values) { - target.assign(source); + if self.data != std::ptr::null_mut() { + let strs = unsafe { std::slice::from_raw_parts_mut(self.data, values.len()) }; + for (target, source) in strs.iter_mut().zip(values) { + target.assign(source); + } } } pub fn to_vec(&self) -> Vec { + if self.data == std::ptr::null_mut() { + return Vec::new(); + } let mut target = Vec::with_capacity(self.size); let strs = unsafe { std::slice::from_raw_parts(self.data, self.size) }; for s in strs { @@ -80,13 +85,18 @@ impl rosidl_runtime_c__String__Sequence { unsafe { rosidl_runtime_c__String__Sequence__init(self as *mut _, values.len()); } - let strs = unsafe { std::slice::from_raw_parts_mut(self.data, values.len()) }; - for (target, source) in strs.iter_mut().zip(values) { - target.assign(source); + if self.data != std::ptr::null_mut() { + let strs = unsafe { std::slice::from_raw_parts_mut(self.data, values.len()) }; + for (target, source) in strs.iter_mut().zip(values) { + target.assign(source); + } } } pub fn to_vec(&self) -> Vec { + if self.data == std::ptr::null_mut() { + return Vec::new(); + } let mut target = Vec::with_capacity(self.size); let strs = unsafe { std::slice::from_raw_parts(self.data, self.size) }; for s in strs { @@ -105,10 +115,15 @@ macro_rules! primitive_sequence { pub fn update(&mut self, values: &[$element_type]) { unsafe { [<$ctype __Sequence__fini>] (self as *mut _); } unsafe { [<$ctype __Sequence__init>] (self as *mut _, values.len()); } - unsafe { std::ptr::copy(values.as_ptr(), self.data, values.len()); } + if self.data != std::ptr::null_mut() { + unsafe { std::ptr::copy(values.as_ptr(), self.data, values.len()); } + } } pub fn to_vec(&self) -> Vec<$element_type> { + if self.data == std::ptr::null_mut() { + return Vec::new(); + } let mut target = Vec::with_capacity(self.size); unsafe { std::ptr::copy(self.data, target.as_mut_ptr(), self.size); diff --git a/tests/test.bash b/tests/test.bash index 7c5ae76..f123204 100644 --- a/tests/test.bash +++ b/tests/test.bash @@ -5,10 +5,6 @@ # run rustup to test with latest rust version rustup update -# temporary fix for CI until #96 is resolved -rustup toolchain install 1.77 -rustup default 1.77 - if [ -e "/opt/ros/iron/setup.bash" ]; then source "/opt/ros/iron/setup.bash" elif [ -e "/opt/ros/humble/setup.bash" ]; then