Skip to main content

ros2_types/
ros_field_type.rs

1//! RosFieldType trait for type-safe field type mapping
2//!
3//! This trait allows types to describe how they should be represented
4//! as ROS2 field types. This eliminates the need for complex type path
5//! analysis in the derive macro.
6
7use crate::types::{
8    FIELD_TYPE_BOOLEAN, FIELD_TYPE_DOUBLE, FIELD_TYPE_FLOAT, FIELD_TYPE_INT8, FIELD_TYPE_INT16,
9    FIELD_TYPE_INT32, FIELD_TYPE_INT64, FIELD_TYPE_NESTED_TYPE, FIELD_TYPE_STRING,
10    FIELD_TYPE_UINT8, FIELD_TYPE_UINT16, FIELD_TYPE_UINT32, FIELD_TYPE_UINT64, FieldType,
11    IndividualTypeDescription,
12};
13
14/// Trait for types that can be used as fields in ROS2 messages.
15///
16/// Each type knows how to describe itself as a ROS2 field type.
17/// This provides a clean, type-safe way to map Rust types to ROS2 field types
18/// without complex compile-time type path analysis.
19pub trait RosFieldType {
20    /// Returns the FieldType for this type when used as a field.
21    fn ros_field_type() -> FieldType;
22
23    /// Returns referenced type descriptions (empty for primitives, populated for nested types).
24    fn referenced_types() -> Vec<IndividualTypeDescription> {
25        vec![]
26    }
27}
28
29// ============================================================================
30// Primitive type implementations
31// ============================================================================
32
33impl RosFieldType for bool {
34    fn ros_field_type() -> FieldType {
35        FieldType::primitive(FIELD_TYPE_BOOLEAN)
36    }
37}
38
39impl RosFieldType for i8 {
40    fn ros_field_type() -> FieldType {
41        FieldType::primitive(FIELD_TYPE_INT8)
42    }
43}
44
45impl RosFieldType for u8 {
46    fn ros_field_type() -> FieldType {
47        FieldType::primitive(FIELD_TYPE_UINT8)
48    }
49}
50
51impl RosFieldType for i16 {
52    fn ros_field_type() -> FieldType {
53        FieldType::primitive(FIELD_TYPE_INT16)
54    }
55}
56
57impl RosFieldType for u16 {
58    fn ros_field_type() -> FieldType {
59        FieldType::primitive(FIELD_TYPE_UINT16)
60    }
61}
62
63impl RosFieldType for i32 {
64    fn ros_field_type() -> FieldType {
65        FieldType::primitive(FIELD_TYPE_INT32)
66    }
67}
68
69impl RosFieldType for u32 {
70    fn ros_field_type() -> FieldType {
71        FieldType::primitive(FIELD_TYPE_UINT32)
72    }
73}
74
75impl RosFieldType for i64 {
76    fn ros_field_type() -> FieldType {
77        FieldType::primitive(FIELD_TYPE_INT64)
78    }
79}
80
81impl RosFieldType for u64 {
82    fn ros_field_type() -> FieldType {
83        FieldType::primitive(FIELD_TYPE_UINT64)
84    }
85}
86
87impl RosFieldType for f32 {
88    fn ros_field_type() -> FieldType {
89        FieldType::primitive(FIELD_TYPE_FLOAT)
90    }
91}
92
93impl RosFieldType for f64 {
94    fn ros_field_type() -> FieldType {
95        FieldType::primitive(FIELD_TYPE_DOUBLE)
96    }
97}
98
99impl RosFieldType for String {
100    fn ros_field_type() -> FieldType {
101        FieldType::primitive(FIELD_TYPE_STRING)
102    }
103}
104
105// ============================================================================
106// Vec<T> implementation - unbounded sequences
107// ============================================================================
108
109impl<T: RosFieldType> RosFieldType for Vec<T> {
110    fn ros_field_type() -> FieldType {
111        let inner = T::ros_field_type();
112        if inner.type_id == FIELD_TYPE_NESTED_TYPE {
113            FieldType::nested_sequence(&inner.nested_type_name)
114        } else {
115            FieldType::sequence(inner.type_id)
116        }
117    }
118
119    fn referenced_types() -> Vec<IndividualTypeDescription> {
120        T::referenced_types()
121    }
122}
123
124// ============================================================================
125// [T; N] implementation - fixed-size arrays
126// ============================================================================
127
128impl<T: RosFieldType, const N: usize> RosFieldType for [T; N] {
129    fn ros_field_type() -> FieldType {
130        let inner = T::ros_field_type();
131        if inner.type_id == FIELD_TYPE_NESTED_TYPE {
132            FieldType::nested_array(&inner.nested_type_name, N as u64)
133        } else {
134            FieldType::array(inner.type_id, N as u64)
135        }
136    }
137
138    fn referenced_types() -> Vec<IndividualTypeDescription> {
139        T::referenced_types()
140    }
141}