rclrs/dynamic_message/
field_access.rs

1use rosidl_runtime_rs::Sequence;
2
3use super::{BaseType, MessageFieldInfo, ValueKind};
4
5mod dynamic_bounded_string;
6mod dynamic_message_view;
7mod dynamic_sequence;
8pub use dynamic_bounded_string::*;
9pub use dynamic_message_view::*;
10pub use dynamic_sequence::*;
11
12// Note:
13// This module defines a bunch of structs in two flavors: immutable and mutable.
14// It's annoying, but imo still better than doing something hard-to-read like
15// https://lab.whitequark.org/notes/2016-12-13/abstracting-over-mutability-in-rust/
16
17/// Helper function for use with reinterpret()/reinterpret_array()
18fn check<T>(bytes: &[u8]) {
19    assert!(bytes.len() >= std::mem::size_of::<T>());
20    let align = std::mem::align_of::<T>();
21    assert_eq!(bytes.as_ptr().align_offset(align), 0);
22}
23
24// The purpose of this macro is to reduce duplication between the value types for the
25// mutable and immutable cases.
26macro_rules! define_value_types {
27    ($select:ident) => {
28
29        // Creates either an immutable or a mutable reference to the type.
30        macro_rules! make_ref { ($lt:lifetime, $type:ty) => {
31            $select!(
32                immutable => &$lt $type,
33                mutable => &$lt mut $type
34            )
35        }}
36
37        /// A single value.
38        // The field variants are for the most part self-explaining.
39        #[allow(missing_docs)]
40        #[derive(Debug, PartialEq)]
41        pub enum SimpleValue<'msg> {
42            Float(make_ref!('msg, f32)),
43            Double(make_ref!('msg, f64)),
44            /// It's platform-dependent what the size of long double is.
45            /// Here's a pointer, you figure it out.
46            LongDouble($select!(
47                immutable => *const u8,
48                mutable => *mut u8
49            )),
50            Char(make_ref!('msg, u8)),
51            WChar(make_ref!('msg, u16)),
52            Boolean(make_ref!('msg, bool)),
53            Octet(make_ref!('msg, u8)),
54            Uint8(make_ref!('msg, u8)),
55            Int8(make_ref!('msg, i8)),
56            Uint16(make_ref!('msg, u16)),
57            Int16(make_ref!('msg, i16)),
58            Uint32(make_ref!('msg, u32)),
59            Int32(make_ref!('msg, i32)),
60            Uint64(make_ref!('msg, u64)),
61            Int64(make_ref!('msg, i64)),
62            String(make_ref!('msg, rosidl_runtime_rs::String)),
63            BoundedString($select!(
64                immutable => DynamicBoundedString<'msg>,
65                mutable => DynamicBoundedStringMut<'msg>
66            )),
67            WString(make_ref!('msg, rosidl_runtime_rs::WString)),
68            BoundedWString($select!(
69                immutable => DynamicBoundedWString<'msg>,
70                mutable => DynamicBoundedWStringMut<'msg>
71            )),
72            Message($select!(
73                immutable => DynamicMessageView<'msg>,
74                mutable => DynamicMessageViewMut<'msg>
75            )),
76        }
77
78        /// An array of values.
79        // The field variants are for the most part self-explaining.
80        #[allow(missing_docs)]
81        #[derive(Debug, PartialEq)]
82        pub enum ArrayValue<'msg> {
83            FloatArray(make_ref!('msg, [f32])),
84            DoubleArray(make_ref!('msg, [f64])),
85            /// It's platform-dependent what the size of long double is.
86            /// Here's a pointer and an array size, you figure it out.
87            LongDoubleArray($select!(
88                immutable => *const u8,
89                mutable => *mut u8
90            ), usize),
91            CharArray(make_ref!('msg, [u8])),
92            WCharArray(make_ref!('msg, [u16])),
93            BooleanArray(make_ref!('msg, [bool])),
94            OctetArray(make_ref!('msg, [u8])),
95            Uint8Array(make_ref!('msg, [u8])),
96            Int8Array(make_ref!('msg, [i8])),
97            Uint16Array(make_ref!('msg, [u16])),
98            Int16Array(make_ref!('msg, [i16])),
99            Uint32Array(make_ref!('msg, [u32])),
100            Int32Array(make_ref!('msg, [i32])),
101            Uint64Array(make_ref!('msg, [u64])),
102            Int64Array(make_ref!('msg, [i64])),
103            StringArray(make_ref!('msg, [rosidl_runtime_rs::String])),
104            BoundedStringArray($select!(
105                immutable => Box<[DynamicBoundedString<'msg>]>,
106                mutable => Box<[DynamicBoundedStringMut<'msg>]>
107            )),
108            WStringArray(make_ref!('msg, [rosidl_runtime_rs::WString])),
109            BoundedWStringArray($select!(
110                immutable => Box<[DynamicBoundedWString<'msg>]>,
111                mutable => Box<[DynamicBoundedWStringMut<'msg>]>
112            )),
113            MessageArray($select!(
114                immutable => Box<[DynamicMessageView<'msg>]>,
115                mutable => Box<[DynamicMessageViewMut<'msg>]>
116            )),
117        }
118
119        /// A sequence of unbounded length.
120        // The field variants are for the most part self-explaining.
121        // Developers: Please also see the explanation in dynamic_sequence.rs.
122        #[allow(missing_docs)]
123        #[derive(Debug, PartialEq)]
124        pub enum SequenceValue<'msg> {
125            FloatSequence(make_ref!('msg, Sequence<f32>)),
126            DoubleSequence(make_ref!('msg, Sequence<f64>)),
127            /// It's platform-dependent what the size of long double is.
128            /// Here's a pointer to the [`Sequence`][1] struct.
129            ///
130            /// [1]: rosidl_runtime_rs::Sequence
131            LongDoubleSequence($select!(
132                immutable => *const u8,
133                mutable => *mut u8
134            )),
135            CharSequence(make_ref!('msg, Sequence<u8>)),
136            WCharSequence(make_ref!('msg, Sequence<u16>)),
137            BooleanSequence(make_ref!('msg, Sequence<bool>)),
138            OctetSequence(make_ref!('msg, Sequence<u8>)),
139            Uint8Sequence(make_ref!('msg, Sequence<u8>)),
140            Int8Sequence(make_ref!('msg, Sequence<i8>)),
141            Uint16Sequence(make_ref!('msg, Sequence<u16>)),
142            Int16Sequence(make_ref!('msg, Sequence<i16>)),
143            Uint32Sequence(make_ref!('msg, Sequence<u32>)),
144            Int32Sequence(make_ref!('msg, Sequence<i32>)),
145            Uint64Sequence(make_ref!('msg, Sequence<u64>)),
146            Int64Sequence(make_ref!('msg, Sequence<i64>)),
147            StringSequence(make_ref!('msg, Sequence<rosidl_runtime_rs::String>)),
148            /// This variant is not a [`Sequence`][1], since there is no suitable element type
149            /// that both matches the underlying struct layout and includes information about
150            /// the string length bound.
151            ///
152            /// [1]: rosidl_runtime_rs::Sequence
153            BoundedStringSequence($select!(
154                immutable => DynamicSequence<'msg, DynamicBoundedString<'msg>>,
155                mutable => DynamicSequenceMut<'msg, DynamicBoundedStringMut<'msg>>
156            )),
157            WStringSequence(make_ref!('msg, Sequence<rosidl_runtime_rs::WString>)),
158            /// This variant is not a [`Sequence`][1], since there is no suitable element type
159            /// that both matches the underlying struct layout and includes information about
160            /// the string length bound.
161            ///
162            /// [1]: rosidl_runtime_rs::Sequence
163            BoundedWStringSequence($select!(
164                immutable => DynamicSequence<'msg, DynamicBoundedWString<'msg>>,
165                mutable => DynamicSequenceMut<'msg, DynamicBoundedWStringMut<'msg>>
166            )),
167            /// This variant is not a [`Sequence<DynamicMessageView>`][1], since the actual
168            /// element type has a different size and layout from [`DynamicMessageView`][2].
169            ///
170            /// [1]: rosidl_runtime_rs::Sequence
171            /// [2]: DynamicMessageView
172            MessageSequence($select!(
173                immutable => DynamicSequence<'msg, DynamicMessageView<'msg>>,
174                mutable => DynamicSequenceMut<'msg, DynamicMessageViewMut<'msg>>)
175            ),
176        }
177
178        // Internal type alias to avoid repeating this a hundred times
179        type BoundedSequence<'msg, T> = $select!(
180            immutable => DynamicBoundedSequence<'msg, T>,
181            mutable => DynamicBoundedSequenceMut<'msg, T>
182        );
183
184        /// A sequence of bounded length.
185        // The field variants are for the most part self-explaining.
186        // Developers: Please also see the explanation in dynamic_sequence.rs.
187        #[allow(missing_docs)]
188        #[derive(Debug, PartialEq)]
189        pub enum BoundedSequenceValue<'msg> {
190            FloatBoundedSequence(BoundedSequence<'msg, f32>),
191            DoubleBoundedSequence(BoundedSequence<'msg, f64>),
192            /// It's platform-dependent what the size of long double is.
193            /// Here's a pointer to the [`BoundedSequence`][1] struct and the upper bound.
194            ///
195            /// [1]: rosidl_runtime_rs::BoundedSequence
196            LongDoubleBoundedSequence($select!(
197                immutable => *const u8,
198                mutable => *mut u8
199            ), usize),
200            CharBoundedSequence(BoundedSequence<'msg, u8>),
201            WCharBoundedSequence(BoundedSequence<'msg, u16>),
202            BooleanBoundedSequence(BoundedSequence<'msg, bool>),
203            OctetBoundedSequence(BoundedSequence<'msg, u8>),
204            Uint8BoundedSequence(BoundedSequence<'msg, u8>),
205            Int8BoundedSequence(BoundedSequence<'msg, i8>),
206            Uint16BoundedSequence(BoundedSequence<'msg, u16>),
207            Int16BoundedSequence(BoundedSequence<'msg, i16>),
208            Uint32BoundedSequence(BoundedSequence<'msg, u32>),
209            Int32BoundedSequence(BoundedSequence<'msg, i32>),
210            Uint64BoundedSequence(BoundedSequence<'msg, u64>),
211            Int64BoundedSequence(BoundedSequence<'msg, i64>),
212            StringBoundedSequence(BoundedSequence<'msg, rosidl_runtime_rs::String>),
213            BoundedStringBoundedSequence($select!(
214                immutable => DynamicBoundedSequence<'msg, DynamicBoundedString<'msg>>,
215                mutable => DynamicBoundedSequenceMut<'msg, DynamicBoundedStringMut<'msg>>)
216            ),
217            WStringBoundedSequence(BoundedSequence<'msg, rosidl_runtime_rs::WString>),
218            BoundedWStringBoundedSequence($select!(
219                immutable => DynamicBoundedSequence<'msg, DynamicBoundedWString<'msg>>,
220                mutable => DynamicBoundedSequenceMut<'msg, DynamicBoundedWStringMut<'msg>>)
221            ),
222            MessageBoundedSequence($select!(
223                immutable => DynamicBoundedSequence<'msg, DynamicMessageView<'msg>>,
224                mutable => DynamicBoundedSequenceMut<'msg, DynamicMessageViewMut<'msg>>)
225            ),
226        }
227
228        // SAFETY: This is in effect a transmutation.
229        //
230        // Here is why this is safe when used as intended, i.e. to reinterpret bytes inside
231        // a dynamic message to their true types, assuming the introspection library is not lying:
232        // * There is no (safe) way for users of rcrls to cause an invalid bit pattern for T to
233        //   be written to the storage of the dynamic message. All accesses are through references to T.
234        // * Correct alignment is ensured during the allocation of the storage for the dynamic message
235        // * The lifetime of the input slice is preserved in the produced reference, so
236        //   this works exactly like borrowing a regular field from a message – the message
237        //   can never be dropped while a borrow exists etc.
238        // * This function does not transmute & to &mut
239        // * This is only used for primitive values and rosidl_runtime_rs types marked as repr(C),
240        //   so there is no risk of reinterpreting as a type with undefined layout.
241        unsafe fn reinterpret<'a, T>(bytes: make_ref!('a, [u8])) -> make_ref!('a, T) {
242            check::<T>(bytes);
243            $select!(
244                immutable => { &*(bytes.as_ptr() as *const T) },
245                mutable => { &mut *(bytes.as_mut_ptr() as *mut T) }
246            )
247        }
248
249        // SAFETY: This is in effect a transmutation. The caller of this function must ensure
250        // that the bytes correspond to a valid [T].
251        //
252        // See also the reinterpret() function.
253        //
254        // std::slice::from_raw_parts is the correct way to transmute a slice.
255        // We can't rely on the internal representation of slices (or other stdlib types).
256        unsafe fn reinterpret_array<'a, T>(bytes: make_ref!('a, [u8]), array_size: usize) -> make_ref!('a, [T]) {
257            check::<T>(bytes);
258            $select!(
259                immutable => { std::slice::from_raw_parts(bytes.as_ptr() as *const T, array_size) },
260                mutable => { std::slice::from_raw_parts_mut(bytes.as_mut_ptr() as *mut T, array_size) }
261            )
262        }
263
264        impl<'msg> SimpleValue<'msg> {
265            pub(super) unsafe fn new(
266                bytes: make_ref!('msg, [u8]),
267                field_info: &'msg MessageFieldInfo,
268            ) -> Self {
269                match &field_info.base_type {
270                    BaseType::Float => SimpleValue::Float(reinterpret::<f32>(bytes)),
271                    BaseType::Double => SimpleValue::Double(reinterpret::<f64>(bytes)),
272                    BaseType::LongDouble => SimpleValue::LongDouble($select!(
273                        immutable => bytes.as_ptr(),
274                        mutable => bytes.as_mut_ptr()
275                    )),
276                    BaseType::Char => SimpleValue::Char(reinterpret::<u8>(bytes)),
277                    BaseType::WChar => SimpleValue::WChar(reinterpret::<u16>(bytes)),
278                    BaseType::Boolean => {
279                        assert!(bytes[0] <= 1);
280                        SimpleValue::Boolean(reinterpret::<bool>(bytes))
281                    }
282                    BaseType::Octet => SimpleValue::Octet(reinterpret::<u8>(bytes)),
283                    BaseType::Uint8 => SimpleValue::Uint8(reinterpret::<u8>(bytes)),
284                    BaseType::Int8 => SimpleValue::Int8(reinterpret::<i8>(bytes)),
285                    BaseType::Uint16 => SimpleValue::Uint16(reinterpret::<u16>(bytes)),
286                    BaseType::Int16 => SimpleValue::Int16(reinterpret::<i16>(bytes)),
287                    BaseType::Uint32 => SimpleValue::Uint32(reinterpret::<u32>(bytes)),
288                    BaseType::Int32 => SimpleValue::Int32(reinterpret::<i32>(bytes)),
289                    BaseType::Uint64 => SimpleValue::Uint64(reinterpret::<u64>(bytes)),
290                    BaseType::Int64 => SimpleValue::Int64(reinterpret::<i64>(bytes)),
291                    BaseType::String => SimpleValue::String(reinterpret::<rosidl_runtime_rs::String>(bytes)),
292                    BaseType::BoundedString { upper_bound } => {
293                        SimpleValue::BoundedString($select!(
294                            immutable => DynamicBoundedString {
295                                inner: reinterpret::<rosidl_runtime_rs::String>(bytes),
296                                upper_bound: *upper_bound,
297                            },
298                            mutable => DynamicBoundedStringMut {
299                                inner: reinterpret::<rosidl_runtime_rs::String>(bytes),
300                                upper_bound: *upper_bound,
301                            }
302                        ))
303                    }
304                    BaseType::WString => SimpleValue::WString(reinterpret::<rosidl_runtime_rs::WString>(bytes)),
305                    BaseType::BoundedWString { upper_bound } => {
306                        SimpleValue::BoundedWString($select!(
307                            immutable => DynamicBoundedWString {
308                                inner: reinterpret::<rosidl_runtime_rs::WString>(bytes),
309                                upper_bound: *upper_bound,
310                            },
311                            mutable => DynamicBoundedWStringMut {
312                                inner: reinterpret::<rosidl_runtime_rs::WString>(bytes),
313                                upper_bound: *upper_bound,
314                            }
315                        ))
316                    }
317                    BaseType::Message(structure) => SimpleValue::Message($select!(
318                        immutable => DynamicMessageView {
319                            storage: &bytes[..structure.size],
320                            structure: &*structure,
321                        },
322                        mutable => DynamicMessageViewMut {
323                            storage: &mut bytes[..structure.size],
324                            structure: &*structure,
325                        }
326                    )),
327                }
328            }
329        }
330
331        impl<'msg> ArrayValue<'msg> {
332            pub(super) unsafe fn new(
333                bytes: make_ref!('msg, [u8]),
334                field_info: &'msg MessageFieldInfo,
335                array_length: usize,
336            ) -> Self {
337                match &field_info.base_type {
338                    BaseType::Float => {
339                        ArrayValue::FloatArray(reinterpret_array::<f32>(bytes, array_length))
340                    }
341                    BaseType::Double => {
342                        ArrayValue::DoubleArray(reinterpret_array::<f64>(bytes, array_length))
343                    }
344                    BaseType::LongDouble => {
345                        ArrayValue::LongDoubleArray($select!(
346                            immutable => bytes.as_ptr(),
347                            mutable => bytes.as_mut_ptr()
348                        ), array_length)
349                    }
350                    BaseType::Char => {
351                        ArrayValue::CharArray(reinterpret_array::<u8>(bytes, array_length))
352                    }
353                    BaseType::WChar => {
354                        ArrayValue::WCharArray(reinterpret_array::<u16>(bytes, array_length))
355                    }
356                    BaseType::Boolean => {
357                        assert!(bytes[0] <= 1);
358                        ArrayValue::BooleanArray(reinterpret_array::<bool>(
359                            bytes,
360                            array_length,
361                        ))
362                    }
363                    BaseType::Octet => {
364                        ArrayValue::OctetArray(reinterpret_array::<u8>(bytes, array_length))
365                    }
366                    BaseType::Uint8 => {
367                        ArrayValue::Uint8Array(reinterpret_array::<u8>(bytes, array_length))
368                    }
369                    BaseType::Int8 => {
370                        ArrayValue::Int8Array(reinterpret_array::<i8>(bytes, array_length))
371                    }
372                    BaseType::Uint16 => {
373                        ArrayValue::Uint16Array(reinterpret_array::<u16>(bytes, array_length))
374                    }
375                    BaseType::Int16 => {
376                        ArrayValue::Int16Array(reinterpret_array::<i16>(bytes, array_length))
377                    }
378                    BaseType::Uint32 => {
379                        ArrayValue::Uint32Array(reinterpret_array::<u32>(bytes, array_length))
380                    }
381                    BaseType::Int32 => {
382                        ArrayValue::Int32Array(reinterpret_array::<i32>(bytes, array_length))
383                    }
384                    BaseType::Uint64 => {
385                        ArrayValue::Uint64Array(reinterpret_array::<u64>(bytes, array_length))
386                    }
387                    BaseType::Int64 => {
388                        ArrayValue::Int64Array(reinterpret_array::<i64>(bytes, array_length))
389                    }
390                    BaseType::String => {
391                        ArrayValue::StringArray(reinterpret_array::<rosidl_runtime_rs::String>(
392                            bytes,
393                            array_length,
394                        ))
395                    }
396                    BaseType::BoundedString { upper_bound } => {
397                        let slice = reinterpret_array::<rosidl_runtime_rs::String>(
398                            bytes,
399                            array_length,
400                        );
401                        let dynamic_bounded_strings: Vec<_> = slice
402                            .into_iter()
403                            .map(|inner| $select!(
404                                immutable => DynamicBoundedString {
405                                    inner,
406                                    upper_bound: *upper_bound,
407                                },
408                                mutable => DynamicBoundedStringMut {
409                                    inner,
410                                    upper_bound: *upper_bound,
411                                }
412                            ))
413                            .collect();
414                        ArrayValue::BoundedStringArray(
415                            dynamic_bounded_strings.into_boxed_slice(),
416                        )
417                    }
418                    BaseType::WString => {
419                        ArrayValue::WStringArray(reinterpret_array::<rosidl_runtime_rs::WString>(
420                            bytes,
421                            array_length,
422                        ))
423                    }
424                    BaseType::BoundedWString { upper_bound } => {
425                        let slice = reinterpret_array::<rosidl_runtime_rs::WString>(
426                            bytes,
427                            array_length,
428                        );
429                        let dynamic_bounded_wstrings: Vec<_> = slice
430                            .into_iter()
431                            .map(|inner| $select!(
432                                immutable => DynamicBoundedWString {
433                                    inner,
434                                    upper_bound: *upper_bound,
435                                },
436                                mutable => DynamicBoundedWStringMut {
437                                    inner,
438                                    upper_bound: *upper_bound,
439                                }
440                            ))
441                            .collect();
442                        ArrayValue::BoundedWStringArray(
443                            dynamic_bounded_wstrings.into_boxed_slice(),
444                        )
445                    }
446                    BaseType::Message(structure) => {
447                        let messages: Vec<_> = $select!(
448                            immutable => bytes.chunks(structure.size)
449                                .take(array_length)
450                                .map(|chunk| DynamicMessageView  {
451                                        storage: chunk,
452                                        structure: &*structure,
453                                })
454                                .collect(),
455                            mutable => bytes.chunks_mut(structure.size)
456                                .take(array_length)
457                                .map(|chunk| DynamicMessageViewMut  {
458                                        storage: chunk,
459                                        structure: &*structure,
460                                })
461                                .collect()
462                        );
463                        ArrayValue::MessageArray(messages.into_boxed_slice())
464                    }
465                }
466            }
467        }
468
469        impl<'msg> SequenceValue<'msg> {
470            pub(super) unsafe fn new(
471                bytes: make_ref!('msg, [u8]),
472                field_info: &'msg MessageFieldInfo,
473            ) -> Self {
474                match &field_info.base_type {
475                    BaseType::Float => {
476                        SequenceValue::FloatSequence(reinterpret::<Sequence<f32>>(bytes))
477                    }
478                    BaseType::Double => {
479                        SequenceValue::DoubleSequence(reinterpret::<Sequence<f64>>(bytes))
480                    }
481                    BaseType::LongDouble => SequenceValue::LongDoubleSequence($select!(
482                        immutable => bytes.as_ptr(),
483                        mutable => bytes.as_mut_ptr()
484                    )),
485                    BaseType::Char => {
486                        SequenceValue::CharSequence(reinterpret::<Sequence<u8>>(bytes))
487                    }
488                    BaseType::WChar => {
489                        SequenceValue::WCharSequence(reinterpret::<Sequence<u16>>(bytes))
490                    }
491                    BaseType::Boolean => {
492                        SequenceValue::BooleanSequence(reinterpret::<Sequence<bool>>(bytes))
493                    }
494                    BaseType::Octet => {
495                        SequenceValue::OctetSequence(reinterpret::<Sequence<u8>>(bytes))
496                    }
497                    BaseType::Uint8 => {
498                        SequenceValue::Uint8Sequence(reinterpret::<Sequence<u8>>(bytes))
499                    }
500                    BaseType::Int8 => {
501                        SequenceValue::Int8Sequence(reinterpret::<Sequence<i8>>(bytes))
502                    }
503                    BaseType::Uint16 => {
504                        SequenceValue::Uint16Sequence(reinterpret::<Sequence<u16>>(bytes))
505                    }
506                    BaseType::Int16 => {
507                        SequenceValue::Int16Sequence(reinterpret::<Sequence<i16>>(bytes))
508                    }
509                    BaseType::Uint32 => {
510                        SequenceValue::Uint32Sequence(reinterpret::<Sequence<u32>>(bytes))
511                    }
512                    BaseType::Int32 => {
513                        SequenceValue::Int32Sequence(reinterpret::<Sequence<i32>>(bytes))
514                    }
515                    BaseType::Uint64 => {
516                        SequenceValue::Uint64Sequence(reinterpret::<Sequence<u64>>(bytes))
517                    }
518                    BaseType::Int64 => {
519                        SequenceValue::Int64Sequence(reinterpret::<Sequence<i64>>(bytes))
520                    }
521                    BaseType::String => {
522                        SequenceValue::StringSequence(reinterpret::<
523                            Sequence<rosidl_runtime_rs::String>,
524                        >(bytes))
525                    }
526                    BaseType::BoundedString { upper_bound } => {
527                        SequenceValue::BoundedStringSequence(
528                            $select!(
529                                immutable => {
530                                    DynamicSequence::new_proxy(
531                                        bytes,
532                                        *upper_bound
533                                    )
534                                },
535                                mutable => DynamicSequenceMut::new_proxy(
536                                    bytes,
537                                    *upper_bound,
538                                    field_info.resize_function.unwrap(),
539                                )
540                            )
541                        )
542                    }
543                    BaseType::WString => {
544                        SequenceValue::WStringSequence(reinterpret::<
545                            Sequence<rosidl_runtime_rs::WString>,
546                        >(bytes))
547                    }
548                    BaseType::BoundedWString { upper_bound } => {
549                        SequenceValue::BoundedWStringSequence(
550                            $select!(
551                                immutable => {
552                                    DynamicSequence::new_proxy(
553                                        bytes,
554                                        *upper_bound
555                                    )
556                                },
557                                mutable => DynamicSequenceMut::new_proxy(
558                                    bytes,
559                                    *upper_bound,
560                                    field_info.resize_function.unwrap(),
561                                )
562                            )
563                        )
564                    }
565                    BaseType::Message(structure) => {
566                        SequenceValue::MessageSequence($select!(
567                            immutable => {
568                                        DynamicSequence::new_proxy(
569                                            bytes,
570                                            &**structure,
571                                        )
572                                    },
573                            mutable => DynamicSequenceMut::new_proxy(
574                                bytes,
575                                &**structure,
576                                field_info.resize_function.unwrap()
577                            )
578                        ))
579                    }
580                }
581            }
582        }
583
584        impl<'msg> BoundedSequenceValue<'msg> {
585            pub(super) unsafe fn new(
586                bytes: make_ref!('msg, [u8]),
587                field_info: &'msg MessageFieldInfo,
588                sequence_upper_bound: usize,
589            ) -> Self {
590                match &field_info.base_type {
591                    BaseType::Float => {
592                        BoundedSequenceValue::FloatBoundedSequence($select!(
593                            immutable => {
594                                DynamicBoundedSequence::new_primitive(
595                                    bytes,
596                                    sequence_upper_bound
597                                )
598                            },
599                            mutable => DynamicBoundedSequenceMut::new_primitive(
600                                bytes,
601                                sequence_upper_bound,
602                                field_info.resize_function.unwrap(),
603                            )
604                        ))
605                    }
606                    BaseType::Double => {
607                        BoundedSequenceValue::DoubleBoundedSequence($select!(
608                            immutable => {
609                                DynamicBoundedSequence::new_primitive(
610                                    bytes,
611                                    sequence_upper_bound
612                                )
613                            },
614                            mutable => DynamicBoundedSequenceMut::new_primitive(
615                                bytes,
616                                sequence_upper_bound,
617                                field_info.resize_function.unwrap(),
618                            )
619                        ))
620                    }
621                    BaseType::LongDouble => BoundedSequenceValue::LongDoubleBoundedSequence(
622                        $select!(
623                            immutable => bytes.as_ptr(),
624                            mutable => bytes.as_mut_ptr()
625                        ),
626                        sequence_upper_bound,
627                    ),
628                    BaseType::Char => {
629                        BoundedSequenceValue::CharBoundedSequence($select!(
630                            immutable => {
631                                DynamicBoundedSequence::new_primitive(
632                                    bytes,
633                                    sequence_upper_bound
634                                )
635                            },
636                            mutable => DynamicBoundedSequenceMut::new_primitive(
637                                bytes,
638                                sequence_upper_bound,
639                                field_info.resize_function.unwrap(),
640                            )
641                        ))
642                    }
643                    BaseType::WChar => {
644                        BoundedSequenceValue::WCharBoundedSequence($select!(
645                            immutable => {
646                                DynamicBoundedSequence::new_primitive(
647                                    bytes,
648                                    sequence_upper_bound
649                                )
650                            },
651                            mutable => DynamicBoundedSequenceMut::new_primitive(
652                                bytes,
653                                sequence_upper_bound,
654                                field_info.resize_function.unwrap(),
655                            )
656                        ))
657                    }
658                    BaseType::Boolean => {
659                        BoundedSequenceValue::BooleanBoundedSequence($select!(
660                            immutable => {
661                                DynamicBoundedSequence::new_primitive(
662                                    bytes,
663                                    sequence_upper_bound
664                                )
665                            },
666                            mutable => DynamicBoundedSequenceMut::new_primitive(
667                                bytes,
668                                sequence_upper_bound,
669                                field_info.resize_function.unwrap(),
670                            )
671                        ))
672                    }
673                    BaseType::Octet => {
674                        BoundedSequenceValue::OctetBoundedSequence($select!(
675                            immutable => {
676                                DynamicBoundedSequence::new_primitive(
677                                    bytes,
678                                    sequence_upper_bound
679                                )
680                            },
681                            mutable => DynamicBoundedSequenceMut::new_primitive(
682                                bytes,
683                                sequence_upper_bound,
684                                field_info.resize_function.unwrap(),
685                            )
686                        ))
687                    }
688                    BaseType::Uint8 => {
689                        BoundedSequenceValue::Uint8BoundedSequence($select!(
690                            immutable => {
691                                DynamicBoundedSequence::new_primitive(
692                                    bytes,
693                                    sequence_upper_bound
694                                )
695                            },
696                            mutable => DynamicBoundedSequenceMut::new_primitive(
697                                bytes,
698                                sequence_upper_bound,
699                                field_info.resize_function.unwrap(),
700                            )
701                        ))
702                    }
703                    BaseType::Int8 => {
704                        BoundedSequenceValue::Int8BoundedSequence($select!(
705                            immutable => {
706                                DynamicBoundedSequence::new_primitive(
707                                    bytes,
708                                    sequence_upper_bound
709                                )
710                            },
711                            mutable => DynamicBoundedSequenceMut::new_primitive(
712                                bytes,
713                                sequence_upper_bound,
714                                field_info.resize_function.unwrap(),
715                            )
716                        ))
717                    }
718                    BaseType::Uint16 => {
719                        BoundedSequenceValue::Uint16BoundedSequence($select!(
720                            immutable => {
721                                DynamicBoundedSequence::new_primitive(
722                                    bytes,
723                                    sequence_upper_bound
724                                )
725                            },
726                            mutable => DynamicBoundedSequenceMut::new_primitive(
727                                bytes,
728                                sequence_upper_bound,
729                                field_info.resize_function.unwrap(),
730                            )
731                        ))
732                    }
733                    BaseType::Int16 => {
734                        BoundedSequenceValue::Int16BoundedSequence($select!(
735                            immutable => {
736                                DynamicBoundedSequence::new_primitive(
737                                    bytes,
738                                    sequence_upper_bound
739                                )
740                            },
741                            mutable => DynamicBoundedSequenceMut::new_primitive(
742                                bytes,
743                                sequence_upper_bound,
744                                field_info.resize_function.unwrap(),
745                            )
746                        ))
747                    }
748                    BaseType::Uint32 => {
749                        BoundedSequenceValue::Uint32BoundedSequence($select!(
750                            immutable => {
751                                DynamicBoundedSequence::new_primitive(
752                                    bytes,
753                                    sequence_upper_bound
754                                )
755                            },
756                            mutable => DynamicBoundedSequenceMut::new_primitive(
757                                bytes,
758                                sequence_upper_bound,
759                                field_info.resize_function.unwrap(),
760                            )
761                        ))
762                    }
763                    BaseType::Int32 => {
764                        BoundedSequenceValue::Int32BoundedSequence($select!(
765                            immutable => {
766                                DynamicBoundedSequence::new_primitive(
767                                    bytes,
768                                    sequence_upper_bound
769                                )
770                            },
771                            mutable => DynamicBoundedSequenceMut::new_primitive(
772                                bytes,
773                                sequence_upper_bound,
774                                field_info.resize_function.unwrap(),
775                            )
776                        ))
777                    }
778                    BaseType::Uint64 => {
779                        BoundedSequenceValue::Uint64BoundedSequence($select!(
780                            immutable => {
781                                DynamicBoundedSequence::new_primitive(
782                                    bytes,
783                                    sequence_upper_bound
784                                )
785                            },
786                            mutable => DynamicBoundedSequenceMut::new_primitive(
787                                bytes,
788                                sequence_upper_bound,
789                                field_info.resize_function.unwrap(),
790                            )
791                        ))
792                    }
793                    BaseType::Int64 => {
794                        BoundedSequenceValue::Int64BoundedSequence($select!(
795                            immutable => {
796                                DynamicBoundedSequence::new_primitive(
797                                    bytes,
798                                    sequence_upper_bound
799                                )
800                            },
801                            mutable => DynamicBoundedSequenceMut::new_primitive(
802                                bytes,
803                                sequence_upper_bound,
804                                field_info.resize_function.unwrap(),
805                            )
806                        ))
807                    }
808                    BaseType::String => {
809                        BoundedSequenceValue::StringBoundedSequence($select!(
810                            immutable => {
811                                DynamicBoundedSequence::new_primitive(
812                                    bytes,
813                                    sequence_upper_bound
814                                )
815                            },
816                            mutable => DynamicBoundedSequenceMut::new_primitive(
817                                bytes,
818                                sequence_upper_bound,
819                                field_info.resize_function.unwrap()
820                            )
821                        ))
822                    }
823                    BaseType::BoundedString { upper_bound } => {
824                        BoundedSequenceValue::BoundedStringBoundedSequence($select!(
825                            immutable => { DynamicBoundedSequence::new_proxy(bytes, sequence_upper_bound, *upper_bound) },
826                            mutable => DynamicBoundedSequenceMut::new_proxy(
827                                bytes,
828                                *upper_bound,
829                                sequence_upper_bound,
830                                field_info.resize_function.unwrap()
831                            )
832                        ))
833                    }
834                    BaseType::WString => {
835                        BoundedSequenceValue::WStringBoundedSequence($select!(
836                            immutable => {
837                                DynamicBoundedSequence::new_primitive(
838                                    bytes,
839                                    sequence_upper_bound
840                                )
841                            },
842                            mutable => DynamicBoundedSequenceMut::new_primitive(
843                                bytes,
844                                sequence_upper_bound,
845                                field_info.resize_function.unwrap()
846                            )
847                        ))
848                    }
849                    BaseType::BoundedWString { upper_bound } => {
850                        BoundedSequenceValue::BoundedWStringBoundedSequence($select!(
851                            immutable => { DynamicBoundedSequence::new_proxy(bytes, sequence_upper_bound, *upper_bound) },
852                            mutable => DynamicBoundedSequenceMut::new_proxy(
853                                bytes,
854                                *upper_bound,
855                                sequence_upper_bound,
856                                field_info.resize_function.unwrap()
857                            )
858                        ))
859                    }
860                    BaseType::Message(structure) => BoundedSequenceValue::MessageBoundedSequence($select!(
861                        immutable => {
862                            DynamicBoundedSequence::new_proxy(bytes, sequence_upper_bound, &**structure)
863                        },
864                        mutable => DynamicBoundedSequenceMut::new_proxy(
865                            bytes,
866                            &**structure,
867                            sequence_upper_bound,
868                            field_info.resize_function.unwrap(),
869                        )
870                    )),
871                }
872            }
873        }
874    };
875}
876
877mod immutable {
878    use super::*;
879
880    macro_rules! select_immutable {
881        (immutable => $a:ty, mutable => $b:ty) => {
882            $a
883        };
884        (immutable => $a:expr, mutable => $b:expr) => {
885            $a
886        };
887    }
888
889    define_value_types!(select_immutable);
890}
891
892pub use immutable::ArrayValue;
893pub use immutable::BoundedSequenceValue;
894pub use immutable::SequenceValue;
895pub use immutable::SimpleValue;
896
897/// The value of a field in a [`DynamicMessage`][1].
898///
899/// This type, and all the types inside it, are reference types – they contain
900/// only a reference to the underlying data.
901///
902/// [1]: crate::dynamic_message::DynamicMessage
903#[derive(Debug, PartialEq)]
904pub enum Value<'msg> {
905    /// A single value.
906    Simple(SimpleValue<'msg>),
907    /// An array of values.
908    Array(ArrayValue<'msg>),
909    /// A sequence of unbounded length.
910    Sequence(SequenceValue<'msg>),
911    /// A sequence of bounded length.
912    BoundedSequence(BoundedSequenceValue<'msg>),
913}
914impl<'msg> Value<'msg> {
915    pub(crate) unsafe fn new(
916        value_bytes: &'msg [u8],
917        field_info: &'msg MessageFieldInfo,
918    ) -> Option<Value<'msg>> {
919        Some(match field_info.value_kind {
920            ValueKind::Simple => Value::Simple(SimpleValue::new(value_bytes, field_info)),
921            ValueKind::Array { length } => {
922                Value::Array(ArrayValue::new(value_bytes, field_info, length))
923            }
924            ValueKind::Sequence => Value::Sequence(SequenceValue::new(value_bytes, field_info)),
925            ValueKind::BoundedSequence { upper_bound } => Value::BoundedSequence(
926                BoundedSequenceValue::new(value_bytes, field_info, upper_bound),
927            ),
928        })
929    }
930}
931
932mod mutable {
933    use super::*;
934
935    macro_rules! select_mutable {
936        (immutable => $a:ty, mutable => $b:ty) => {
937            $b
938        };
939        (immutable => $a:expr, mutable => $b:expr) => {
940            $b
941        };
942    }
943
944    define_value_types!(select_mutable);
945}
946
947pub use mutable::ArrayValue as ArrayValueMut;
948pub use mutable::BoundedSequenceValue as BoundedSequenceValueMut;
949pub use mutable::SequenceValue as SequenceValueMut;
950pub use mutable::SimpleValue as SimpleValueMut;
951
952/// The value of a field in a [`DynamicMessage`][1].
953///
954/// This type, and all the types inside it, are reference types – they contain
955/// only a reference to the underlying data.
956///
957/// [1]: crate::dynamic_message::DynamicMessage
958#[derive(Debug, PartialEq)]
959pub enum ValueMut<'msg> {
960    /// A single value.
961    Simple(SimpleValueMut<'msg>),
962    /// An array of values.
963    Array(ArrayValueMut<'msg>),
964    /// A sequence of unbounded length.
965    Sequence(SequenceValueMut<'msg>),
966    /// A sequence of bounded length.
967    BoundedSequence(BoundedSequenceValueMut<'msg>),
968}
969
970impl<'msg> ValueMut<'msg> {
971    pub(crate) unsafe fn new(
972        value_bytes: &'msg mut [u8],
973        field_info: &'msg MessageFieldInfo,
974    ) -> ValueMut<'msg> {
975        match field_info.value_kind {
976            ValueKind::Simple => ValueMut::Simple(SimpleValueMut::new(value_bytes, field_info)),
977            ValueKind::Array { length } => {
978                ValueMut::Array(ArrayValueMut::new(value_bytes, field_info, length))
979            }
980            ValueKind::Sequence => {
981                ValueMut::Sequence(SequenceValueMut::new(value_bytes, field_info))
982            }
983            ValueKind::BoundedSequence { upper_bound } => ValueMut::BoundedSequence(
984                BoundedSequenceValueMut::new(value_bytes, field_info, upper_bound),
985            ),
986        }
987    }
988}