1use std::fmt::Display;
5
6#[cfg(feature = "rcl")]
10mod rcl_impl {
11 use crate::rcl::*;
12
13 macro_rules! def_sequence {
14 ($ty: ident, $ty_orig:ty, $ty_seq:ty, $init:ident, $fini:ident, $eq:ident, $copy:ident) => {
15 #[repr(C)]
19 #[derive(Debug)]
20 pub struct $ty<const N: usize>($ty_seq);
21
22 impl<const N: usize> $ty<N> {
23 pub fn new(size: usize) -> Option<Self> {
24 if N != 0 && size > N {
25 return None;
27 }
28
29 let mut msg: $ty_seq = unsafe { std::mem::zeroed() };
30 if unsafe { $init(&mut msg, size as _) } {
31 Some($ty(msg))
32 } else {
33 None
34 }
35 }
36
37 pub fn null() -> Self {
38 let msg: $ty_seq = unsafe { std::mem::zeroed() };
39 $ty(msg)
40 }
41
42 pub fn as_slice(&self) -> &[$ty_orig] {
43 if self.0.data.is_null() {
44 &[]
45 } else {
46 let s = unsafe {
47 std::slice::from_raw_parts(self.0.data, self.0.size as usize)
48 };
49 s
50 }
51 }
52
53 pub fn as_mut_slice(&mut self) -> &mut [$ty_orig] {
54 if self.0.data.is_null() {
55 &mut []
56 } else {
57 let s = unsafe {
58 std::slice::from_raw_parts_mut(self.0.data, self.0.size as usize)
59 };
60 s
61 }
62 }
63
64 pub fn iter(&self) -> std::slice::Iter<'_, $ty_orig> {
65 self.as_slice().iter()
66 }
67
68 pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, $ty_orig> {
69 self.as_mut_slice().iter_mut()
70 }
71
72 pub fn len(&self) -> usize {
73 self.as_slice().len()
74 }
75
76 pub fn is_empty(&self) -> bool {
77 self.len() == 0
78 }
79 }
80
81 impl<const N: usize> Drop for $ty<N> {
82 fn drop(&mut self) {
83 unsafe { $fini(&mut self.0 as *mut _) };
84 }
85 }
86
87 impl<const N: usize> PartialEq for $ty<N> {
88 fn eq(&self, other: &Self) -> bool {
89 unsafe { $eq(&self.0, &other.0) }
90 }
91 }
92
93 impl<const N: usize> ::oxidros_core::msg::TryClone for $ty<N> {
94 fn try_clone(&self) -> Option<Self> {
95 let mut result = Self::new(self.0.size)?;
96 if unsafe { $copy(&self.0, &mut result.0) } {
97 Some(result)
98 } else {
99 None
100 }
101 }
102 }
103
104 impl<const N: usize> Clone for $ty<N> {
105 fn clone(&self) -> Self {
106 ::oxidros_core::msg::TryClone::try_clone(self).unwrap()
107 }
108 }
109
110 impl<const N: usize> Default for $ty<N> {
111 fn default() -> Self {
112 Self::null()
113 }
114 }
115
116 unsafe impl<const N: usize> Sync for $ty<N> {}
117 unsafe impl<const N: usize> Send for $ty<N> {}
118 };
119 }
120
121 def_sequence!(
122 BoolSeq,
123 bool,
124 rosidl_runtime_c__boolean__Sequence,
125 rosidl_runtime_c__boolean__Sequence__init,
126 rosidl_runtime_c__boolean__Sequence__fini,
127 rosidl_runtime_c__boolean__Sequence__are_equal,
128 rosidl_runtime_c__boolean__Sequence__copy
129 );
130
131 def_sequence!(
132 F32Seq,
133 f32,
134 rosidl_runtime_c__float__Sequence,
135 rosidl_runtime_c__float__Sequence__init,
136 rosidl_runtime_c__float__Sequence__fini,
137 rosidl_runtime_c__float__Sequence__are_equal,
138 rosidl_runtime_c__float__Sequence__copy
139 );
140
141 def_sequence!(
142 F64Seq,
143 f64,
144 rosidl_runtime_c__double__Sequence,
145 rosidl_runtime_c__double__Sequence__init,
146 rosidl_runtime_c__double__Sequence__fini,
147 rosidl_runtime_c__double__Sequence__are_equal,
148 rosidl_runtime_c__double__Sequence__copy
149 );
150
151 def_sequence!(
152 U8Seq,
153 u8,
154 rosidl_runtime_c__uint8__Sequence,
155 rosidl_runtime_c__uint8__Sequence__init,
156 rosidl_runtime_c__uint8__Sequence__fini,
157 rosidl_runtime_c__uint8__Sequence__are_equal,
158 rosidl_runtime_c__uint8__Sequence__copy
159 );
160
161 def_sequence!(
164 ByteSeq,
165 u8,
166 rosidl_runtime_c__octet__Sequence,
167 rosidl_runtime_c__octet__Sequence__init,
168 rosidl_runtime_c__octet__Sequence__fini,
169 rosidl_runtime_c__octet__Sequence__are_equal,
170 rosidl_runtime_c__octet__Sequence__copy
171 );
172
173 def_sequence!(
174 I8Seq,
175 i8,
176 rosidl_runtime_c__int8__Sequence,
177 rosidl_runtime_c__int8__Sequence__init,
178 rosidl_runtime_c__int8__Sequence__fini,
179 rosidl_runtime_c__int8__Sequence__are_equal,
180 rosidl_runtime_c__int8__Sequence__copy
181 );
182 def_sequence!(
183 U16Seq,
184 u16,
185 rosidl_runtime_c__uint16__Sequence,
186 rosidl_runtime_c__uint16__Sequence__init,
187 rosidl_runtime_c__uint16__Sequence__fini,
188 rosidl_runtime_c__uint16__Sequence__are_equal,
189 rosidl_runtime_c__uint16__Sequence__copy
190 );
191
192 def_sequence!(
193 I16Seq,
194 i16,
195 rosidl_runtime_c__int16__Sequence,
196 rosidl_runtime_c__int16__Sequence__init,
197 rosidl_runtime_c__int16__Sequence__fini,
198 rosidl_runtime_c__int16__Sequence__are_equal,
199 rosidl_runtime_c__int16__Sequence__copy
200 );
201
202 def_sequence!(
203 U32Seq,
204 u32,
205 rosidl_runtime_c__uint32__Sequence,
206 rosidl_runtime_c__uint32__Sequence__init,
207 rosidl_runtime_c__uint32__Sequence__fini,
208 rosidl_runtime_c__uint32__Sequence__are_equal,
209 rosidl_runtime_c__uint32__Sequence__copy
210 );
211
212 def_sequence!(
213 I32Seq,
214 i32,
215 rosidl_runtime_c__int32__Sequence,
216 rosidl_runtime_c__int32__Sequence__init,
217 rosidl_runtime_c__int32__Sequence__fini,
218 rosidl_runtime_c__int32__Sequence__are_equal,
219 rosidl_runtime_c__int32__Sequence__copy
220 );
221
222 def_sequence!(
223 U64Seq,
224 u64,
225 rosidl_runtime_c__uint64__Sequence,
226 rosidl_runtime_c__uint64__Sequence__init,
227 rosidl_runtime_c__uint64__Sequence__fini,
228 rosidl_runtime_c__uint64__Sequence__are_equal,
229 rosidl_runtime_c__uint64__Sequence__copy
230 );
231
232 def_sequence!(
233 I64Seq,
234 i64,
235 rosidl_runtime_c__int64__Sequence,
236 rosidl_runtime_c__int64__Sequence__init,
237 rosidl_runtime_c__int64__Sequence__fini,
238 rosidl_runtime_c__int64__Sequence__are_equal,
239 rosidl_runtime_c__int64__Sequence__copy
240 );
241}
242
243#[cfg(not(feature = "rcl"))]
247mod non_rcl_impl {
248 use ros2_types::serde::{Deserialize, Deserializer, Serialize, Serializer};
249
250 macro_rules! def_sequence {
251 ($ty: ident, $ty_orig:ty) => {
252 #[derive(Debug)]
256 pub struct $ty<const N: usize>(Vec<$ty_orig>);
257
258 impl<const N: usize> $ty<N> {
259 pub fn new(size: usize) -> Option<Self> {
260 if N != 0 && size > N {
261 return None;
263 }
264 Some($ty(vec![Default::default(); size]))
265 }
266
267 pub fn null() -> Self {
268 $ty(Vec::new())
269 }
270
271 pub fn as_slice(&self) -> &[$ty_orig] {
272 &self.0
273 }
274
275 pub fn as_mut_slice(&mut self) -> &mut [$ty_orig] {
276 &mut self.0
277 }
278
279 pub fn iter(&self) -> std::slice::Iter<'_, $ty_orig> {
280 self.0.iter()
281 }
282
283 pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, $ty_orig> {
284 self.0.iter_mut()
285 }
286
287 pub fn len(&self) -> usize {
288 self.0.len()
289 }
290
291 pub fn is_empty(&self) -> bool {
292 self.0.is_empty()
293 }
294 }
295
296 impl<const N: usize> PartialEq for $ty<N> {
297 fn eq(&self, other: &Self) -> bool {
298 self.0 == other.0
299 }
300 }
301
302 impl<const N: usize> ::oxidros_core::msg::TryClone for $ty<N> {
303 fn try_clone(&self) -> Option<Self> {
304 Some($ty(self.0.clone()))
305 }
306 }
307
308 impl<const N: usize> Clone for $ty<N> {
309 fn clone(&self) -> Self {
310 $ty(self.0.clone())
311 }
312 }
313
314 impl<const N: usize> Default for $ty<N> {
315 fn default() -> Self {
316 Self::null()
317 }
318 }
319
320 impl<const N: usize> Serialize for $ty<N> {
321 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
322 where
323 S: Serializer,
324 {
325 self.0.serialize(serializer)
326 }
327 }
328
329 impl<'de, const N: usize> Deserialize<'de> for $ty<N> {
330 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
331 where
332 D: Deserializer<'de>,
333 {
334 let vec = Vec::<$ty_orig>::deserialize(deserializer)?;
335 if N != 0 && vec.len() > N {
336 return Err(ros2_types::serde::de::Error::custom(format!(
337 "sequence length {} exceeds maximum {}",
338 vec.len(),
339 N
340 )));
341 }
342 Ok($ty(vec))
343 }
344 }
345
346 unsafe impl<const N: usize> Sync for $ty<N> {}
347 unsafe impl<const N: usize> Send for $ty<N> {}
348 };
349 }
350
351 def_sequence!(BoolSeq, bool);
352 def_sequence!(F32Seq, f32);
353 def_sequence!(F64Seq, f64);
354 def_sequence!(U8Seq, u8);
355 def_sequence!(ByteSeq, u8); def_sequence!(I8Seq, i8);
357 def_sequence!(U16Seq, u16);
358 def_sequence!(I16Seq, i16);
359 def_sequence!(U32Seq, u32);
360 def_sequence!(I32Seq, i32);
361 def_sequence!(U64Seq, u64);
362 def_sequence!(I64Seq, i64);
363}
364
365#[cfg(feature = "rcl")]
369pub use rcl_impl::*;
370
371#[cfg(not(feature = "rcl"))]
372pub use non_rcl_impl::*;
373
374#[derive(Debug, Copy, Clone)]
380pub struct TryFromSliceError(());
381
382impl std::fmt::Display for TryFromSliceError {
383 #[inline]
384 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
385 "could not convert slice to array".fmt(f)
386 }
387}
388
389impl std::error::Error for TryFromSliceError {}
390
391macro_rules! def_try_from {
392 ($from:ty, $to:ty) => {
393 impl TryFrom<&[$from]> for $to {
394 type Error = TryFromSliceError;
395 fn try_from(value: &[$from]) -> Result<Self, Self::Error> {
396 let mut seq = Self::new(value.len()).ok_or(TryFromSliceError(()))?;
397 seq.iter_mut().zip(value).for_each(|(dst, &src)| *dst = src);
398 Ok(seq)
399 }
400 }
401 };
402}
403
404def_try_from!(bool, BoolSeq<0>);
405def_try_from!(i8, I8Seq<0>);
406def_try_from!(i16, I16Seq<0>);
407def_try_from!(i32, I32Seq<0>);
408def_try_from!(i64, I64Seq<0>);
409def_try_from!(u8, U8Seq<0>);
410def_try_from!(u16, U16Seq<0>);
411def_try_from!(u32, U32Seq<0>);
412def_try_from!(u64, U64Seq<0>);
413def_try_from!(f32, F32Seq<0>);
414def_try_from!(f64, F64Seq<0>);
415
416#[cfg(test)]
417mod tests {
418 use oxidros_core::msg::TryClone;
419
420 use super::*;
421
422 #[test]
423 fn test_clone() {
424 let v1: BoolSeq<0> = [true; 10].as_slice().try_into().unwrap();
425 let v2 = v1.try_clone().unwrap();
426 assert_eq!(v1, v2);
427 let v1: U32Seq<0> = [2; 10].as_slice().try_into().unwrap();
428 let v2 = v1.try_clone().unwrap();
429 assert_eq!(v1, v2);
430 }
431}
432
433use ros2_types::RosFieldType;
438use ros2_types::types::FieldType;
439
440macro_rules! impl_ros_field_type_seq {
441 ($ty:ident, $type_id:ident) => {
442 impl<const N: usize> RosFieldType for $ty<N> {
443 fn ros_field_type() -> FieldType {
444 if N == 0 {
445 FieldType::sequence(ros2_types::$type_id)
446 } else {
447 FieldType::bounded_sequence(ros2_types::$type_id, N as u64)
448 }
449 }
450 }
451 };
452}
453
454impl_ros_field_type_seq!(BoolSeq, FIELD_TYPE_BOOLEAN);
455impl_ros_field_type_seq!(I8Seq, FIELD_TYPE_INT8);
456impl_ros_field_type_seq!(U8Seq, FIELD_TYPE_UINT8);
457impl_ros_field_type_seq!(ByteSeq, FIELD_TYPE_BYTE);
458impl_ros_field_type_seq!(I16Seq, FIELD_TYPE_INT16);
459impl_ros_field_type_seq!(U16Seq, FIELD_TYPE_UINT16);
460impl_ros_field_type_seq!(I32Seq, FIELD_TYPE_INT32);
461impl_ros_field_type_seq!(U32Seq, FIELD_TYPE_UINT32);
462impl_ros_field_type_seq!(I64Seq, FIELD_TYPE_INT64);
463impl_ros_field_type_seq!(U64Seq, FIELD_TYPE_UINT64);
464impl_ros_field_type_seq!(F32Seq, FIELD_TYPE_FLOAT);
465impl_ros_field_type_seq!(F64Seq, FIELD_TYPE_DOUBLE);