@@ -20,9 +20,24 @@ use serde::{Deserialize, Serialize};
20
20
#[ derive( Default , Debug , Clone , Eq , Hash , PartialEq , Serialize , Deserialize ) ]
21
21
pub enum TypeVariant {
22
22
#[ default]
23
- /// A fixed size type like [`u64`]
23
+ /// A type notated by [`#[repr(C)]`](https://doc.rust-lang.org/reference/type-layout.html#reprc).
24
+ /// with a constant size known at compile time is recognized as FixedSize.
25
+ /// The FixedSize type should satisfy the [`Sized`].
26
+ /// For example, all primitive types are FixedSize. The self-contained structs(without pointer members
27
+ /// or heap-usages) are FixedSize.
24
28
FixedSize ,
25
- /// A dynamic sized type like a slice
29
+
30
+ /// A dynamic sized type strictly refers to the slice of an iceoryx2 compatible types.
31
+ /// The struct with pointer members or with heap usage MUSTN't be recognized as Dynamic type.
32
+ /// Indeed, they're the in-compatible iceoryx2 types.
33
+ ///
34
+ /// The underlying reason is the shared memory which we use to store the payload data.
35
+ /// If the payload type would use the heap then the type would use
36
+ /// process local memory that is not available to another process.
37
+ ///
38
+ /// The pointer requirement comes again from shared memory.
39
+ /// It has a different pointer address offset in every process rendering any absolute pointer
40
+ /// useless and dereferencing it would end up in a segfault.
26
41
Dynamic ,
27
42
}
28
43
@@ -33,9 +48,10 @@ pub struct TypeDetail {
33
48
pub variant : TypeVariant ,
34
49
/// Contains the output of [`core::any::type_name()`].
35
50
pub type_name : String ,
36
- /// The size of the underlying type.
51
+ /// The size of the underlying type calculated by [`core::mem::size_of`] .
37
52
pub size : usize ,
38
- /// The alignment of the underlying type.
53
+ /// The ABI-required minimum alignment of the underlying type calculated by [`core::mem::align_of`].
54
+ /// It may be set by users with a larger alignment, e.g. the memory provided by allocator used by SIMD.
39
55
pub alignment : usize ,
40
56
}
41
57
@@ -64,11 +80,11 @@ pub struct MessageTypeDetails {
64
80
}
65
81
66
82
impl MessageTypeDetails {
67
- pub ( crate ) fn from < Header , UserHeader , Payload > ( variant : TypeVariant ) -> Self {
83
+ pub ( crate ) fn from < Header , UserHeader , Payload > ( payload_variant : TypeVariant ) -> Self {
68
84
Self {
69
85
header : TypeDetail :: __internal_new :: < Header > ( TypeVariant :: FixedSize ) ,
70
86
user_header : TypeDetail :: __internal_new :: < UserHeader > ( TypeVariant :: FixedSize ) ,
71
- payload : TypeDetail :: __internal_new :: < Payload > ( variant ) ,
87
+ payload : TypeDetail :: __internal_new :: < Payload > ( payload_variant ) ,
72
88
}
73
89
}
74
90
@@ -78,6 +94,7 @@ impl MessageTypeDetails {
78
94
payload_start as * const u8
79
95
}
80
96
97
+ /// returns the pointer to the user header
81
98
pub ( crate ) fn user_header_ptr_from_header ( & self , header : * const u8 ) -> * const u8 {
82
99
let header = header as usize ;
83
100
let user_header_start = align ( header + self . header . size , self . user_header . alignment ) ;
@@ -120,3 +137,133 @@ impl MessageTypeDetails {
120
137
&& self . payload . alignment <= rhs. payload . alignment
121
138
}
122
139
}
140
+
141
+ #[ cfg( test) ]
142
+ mod tests {
143
+ use super :: * ;
144
+ use iceoryx2_bb_testing:: assert_that;
145
+
146
+ #[ cfg( target_pointer_width = "32" ) ]
147
+ const ALIGNMENT : usize = 4 ;
148
+ #[ cfg( target_pointer_width = "64" ) ]
149
+ const ALIGNMENT : usize = 8 ;
150
+
151
+ #[ test]
152
+ fn test_from ( ) {
153
+ #[ repr( C ) ]
154
+ struct MyPayload {
155
+ _a : i32 ,
156
+ _b : bool ,
157
+ _c : i64 ,
158
+ }
159
+
160
+ let sut = MessageTypeDetails :: from :: < i32 , i64 , MyPayload > ( TypeVariant :: FixedSize ) ;
161
+ let expected = MessageTypeDetails {
162
+ header : TypeDetail {
163
+ variant : TypeVariant :: FixedSize ,
164
+ type_name : "i32" . to_string ( ) ,
165
+ size : 4 ,
166
+ alignment : 4 , // i32 uses 4 bytes, so its aliment is always 4 no matter x32 or x64.
167
+ } ,
168
+ user_header : TypeDetail {
169
+ variant : TypeVariant :: FixedSize ,
170
+ type_name : "i64" . to_string ( ) ,
171
+ size : 8 ,
172
+ alignment : ALIGNMENT ,
173
+ } ,
174
+ payload : TypeDetail {
175
+ variant : TypeVariant :: FixedSize ,
176
+ type_name : "iceoryx2::service::static_config::message_type_details::tests::test_from::MyPayload" . to_string ( ) ,
177
+ size : 16 ,
178
+ alignment : ALIGNMENT ,
179
+ } ,
180
+ } ;
181
+ assert_that ! ( sut, eq expected) ;
182
+
183
+ let sut = MessageTypeDetails :: from :: < i32 , bool , i64 > ( TypeVariant :: Dynamic ) ;
184
+ let expected = MessageTypeDetails {
185
+ header : TypeDetail {
186
+ variant : TypeVariant :: FixedSize ,
187
+ type_name : "i32" . to_string ( ) ,
188
+ size : 4 ,
189
+ alignment : 4 ,
190
+ } ,
191
+ user_header : TypeDetail {
192
+ variant : TypeVariant :: FixedSize ,
193
+ type_name : "bool" . to_string ( ) ,
194
+ size : 1 ,
195
+ alignment : 1 ,
196
+ } ,
197
+ payload : TypeDetail {
198
+ variant : TypeVariant :: Dynamic ,
199
+ type_name : "i64" . to_string ( ) ,
200
+ size : 8 ,
201
+ alignment : ALIGNMENT ,
202
+ } ,
203
+ } ;
204
+ assert_that ! ( sut, eq expected) ;
205
+ }
206
+
207
+ #[ test]
208
+ fn test_user_header_ptr_from_header ( ) {
209
+ let details = MessageTypeDetails :: from :: < i32 , bool , i64 > ( TypeVariant :: Dynamic ) ;
210
+ #[ repr( C ) ]
211
+ struct Demo {
212
+ header : i32 ,
213
+ user_header : bool ,
214
+ _payload : i64 ,
215
+ }
216
+
217
+ let demo = Demo {
218
+ header : 123 ,
219
+ user_header : true ,
220
+ _payload : 123 ,
221
+ } ;
222
+
223
+ let ptr: * const u8 = & demo. header as * const _ as * const u8 ;
224
+ let user_header_ptr = details. user_header_ptr_from_header ( ptr) ;
225
+ let sut: * const bool = user_header_ptr as * const bool ;
226
+ assert_that ! ( unsafe { * sut } , eq demo. user_header) ;
227
+
228
+ let details = MessageTypeDetails :: from :: < i64 , i32 , i64 > ( TypeVariant :: Dynamic ) ;
229
+ #[ repr( C ) ]
230
+ struct Demo2 {
231
+ header : i64 ,
232
+ user_header : i32 ,
233
+ _payload : i64 ,
234
+ }
235
+
236
+ let demo = Demo2 {
237
+ header : 123 ,
238
+ user_header : 999 ,
239
+ _payload : 123 ,
240
+ } ;
241
+
242
+ let ptr: * const u8 = & demo. header as * const _ as * const u8 ;
243
+ let user_header_ptr = details. user_header_ptr_from_header ( ptr) ;
244
+ let sut: * const i32 = user_header_ptr as * const i32 ;
245
+ assert_that ! ( unsafe { * sut } , eq demo. user_header) ;
246
+ }
247
+
248
+ #[ test]
249
+ fn test_payload_ptr_from_header ( ) {
250
+ let details = MessageTypeDetails :: from :: < i32 , i32 , i32 > ( TypeVariant :: Dynamic ) ;
251
+ #[ repr( C ) ]
252
+ struct Demo {
253
+ header : i32 ,
254
+ _user_header : i32 ,
255
+ payload : i32 ,
256
+ }
257
+
258
+ let demo = Demo {
259
+ header : 123 ,
260
+ _user_header : 123 ,
261
+ payload : 9999 ,
262
+ } ;
263
+
264
+ let ptr: * const u8 = & demo. header as * const _ as * const u8 ;
265
+ let payload_ptr = details. payload_ptr_from_header ( ptr) as * const i32 ;
266
+ let sut = unsafe { * payload_ptr } ;
267
+ assert_that ! ( sut, eq demo. payload) ;
268
+ }
269
+ }
0 commit comments