Skip to content

Commit

Permalink
no_std compatible (#18)
Browse files Browse the repository at this point in the history
  • Loading branch information
stelzo authored May 15, 2024
1 parent 56c29ac commit fc15b9e
Show file tree
Hide file tree
Showing 6 changed files with 185 additions and 67 deletions.
5 changes: 3 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ r2r = { version = "0.8.4", optional = true }
rayon = { version = "1", optional = true }
nalgebra = { version = "0", optional = true }
rpcl2_derive = { path = "./rpcl2_derive", optional = true }
type-layout = { version = "0.2", optional = true }
type-layout = { git = "https://github.com/stelzo/type-layout", branch = "syn2", optional = true }

[dev-dependencies]
rand = "0.8"
Expand All @@ -51,8 +51,9 @@ r2r_msg = ["dep:r2r"]
rayon = ["dep:rayon"]
derive = ["dep:rpcl2_derive", "dep:type-layout"]
nalgebra = ["dep:nalgebra"]
std = []

default = ["derive"]
default = ["derive", "std"]

[package.metadata.docs.rs]
features = ["derive", "nalgebra", "rayon"]
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,10 @@ The results are measured on an Intel i7-14700 with benchmarks from [this reposit

For minimizing the conversion overhead in general, always use the functions that best fit your use case.

## `#[no_std]`

The `_iter` conversions are compatible with `#[no_std]` environments when an allocator is provided. This is due to the fact that names for point fields do not have a maximum length, and PointCloud2 data vectors can have arbitrary sizes. Use `default-features = false` to disable std for this crate.

## License

[MIT](https://choosealicense.com/licenses/mit/)
35 changes: 26 additions & 9 deletions src/iterator.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,19 @@
//! Iterator implementations for PointCloud2Msg including a parallel iterator for rayon.
//! Iterator implementations for [`PointCloud2Msg`] including a parallel iterator for rayon.
use crate::{
Endian, FieldDatatype, Fields, MsgConversionError, PointCloud2Msg, PointConvertible, PointData,
RPCL2Point,
};

/// The PointCloudIterator provides a an iterator abstraction of the PointCloud2Msg.
#[cfg(not(feature = "std"))]
use alloc::string::String;

#[cfg(not(feature = "std"))]
use alloc::vec::Vec;

#[cfg(not(feature = "std"))]
use alloc::borrow::ToOwned;

/// The PointCloudIterator provides a an iterator abstraction of the [`PointCloud2Msg`].
///
/// The iterator is defined at compile time, so the point has to be described via template arguments.
///
Expand All @@ -19,7 +28,7 @@ use crate::{
/// let msg: r2r::sensor_msgs::msg::PointCloud2 = internal_msg.into();
/// let converted: ros_pointcloud2::PointCloud2Msg = msg.into();
///
/// ros_pointcloud2 supports r2r, rclrs and rosrust as conversion targets out of the box via feature flags.
/// `ros_pointcloud2` supports r2r, rclrs and rosrust as conversion targets out of the box via feature flags.
///
pub struct PointCloudIterator<const N: usize, C>
where
Expand All @@ -28,7 +37,7 @@ where
iteration: usize,
iteration_back: usize,
data: ByteBufferView<N>,
phantom_c: std::marker::PhantomData<C>, // internally used for pdata names array
phantom_c: core::marker::PhantomData<C>, // internally used for pdata names array
}

#[cfg(feature = "rayon")]
Expand Down Expand Up @@ -156,7 +165,10 @@ where
}

struct ByteBufferView<const N: usize> {
#[cfg(feature = "rayon")]
data: std::sync::Arc<[u8]>,
#[cfg(not(feature = "rayon"))]
data: Vec<u8>,
start_point_idx: usize,
end_point_idx: usize,
point_step_size: usize,
Expand All @@ -176,7 +188,10 @@ impl<const N: usize> ByteBufferView<N> {
endian: Endian,
) -> Self {
Self {
#[cfg(feature = "rayon")]
data: std::sync::Arc::<[u8]>::from(data),
#[cfg(not(feature = "rayon"))]
data,
start_point_idx,
end_point_idx,
point_step_size,
Expand All @@ -191,7 +206,7 @@ impl<const N: usize> ByteBufferView<N> {
self.end_point_idx - self.start_point_idx + 1
}

#[inline(always)]
#[inline]
fn point_at(&self, idx: usize) -> RPCL2Point<N> {
let offset = (self.start_point_idx + idx) * self.point_step_size;
let mut pdata = [PointData::default(); N];
Expand Down Expand Up @@ -244,8 +259,8 @@ where
{
type Error = MsgConversionError;

/// Convert a PointCloud2Msg into an iterator.
/// Converting a PointCloud2Msg into an iterator is a fallible operation since the message could contain a subset of the required fields.
/// Convert a [`PointCloud2Msg`] into an iterator.
/// The conversion to an iterator is a fallible operation since the message could contain a subset of the required fields.
///
/// The theoretical time complexity is O(n) where n is the number of fields defined in the message for a single point which is typically small.
/// It therefore has a constant time complexity O(1) for practical purposes.
Expand Down Expand Up @@ -332,7 +347,7 @@ where
iteration: 0,
iteration_back: cloud_length - 1,
data,
phantom_c: std::marker::PhantomData,
phantom_c: core::marker::PhantomData,
})
}
}
Expand All @@ -342,16 +357,18 @@ where
C: Fields<N>,
{
#[inline]
#[must_use]
fn from_byte_buffer_view(data: ByteBufferView<N>) -> Self {
Self {
iteration: 0,
iteration_back: data.len() - 1,
data,
phantom_c: std::marker::PhantomData,
phantom_c: core::marker::PhantomData,
}
}

#[inline]
#[must_use]
pub fn split_at(self, point_index: usize) -> (Self, Self) {
let (left_data, right_data) = self.data.split_at(point_index);
(
Expand Down
Loading

0 comments on commit fc15b9e

Please sign in to comment.