@@ -140,5 +140,50 @@ fn panic(_info: &PanicInfo) -> ! {
140
140
}
141
141
}
142
142
143
+ /// Calculates the offset of a field from the beginning of the struct it belongs to.
144
+ #[ macro_export]
145
+ macro_rules! offset_of {
146
+ ( $type: ty, $( $f: tt) * ) => { {
147
+ let tmp = core:: mem:: MaybeUninit :: <$type>:: uninit( ) ;
148
+ let ptr = tmp. as_ptr( ) ;
149
+ #[ allow( unused_unsafe) ]
150
+ let dev = unsafe { core:: ptr:: addr_of!( ( * ptr) . $( $f) * ) as * const u8 } ;
151
+ #[ allow( unused_unsafe) ]
152
+ unsafe { dev. offset_from( ptr as * const u8 ) }
153
+ } }
154
+ }
155
+
156
+ /// Produces a pointer to an object from a pointer to one of its fields.
157
+ ///
158
+ /// # Safety
159
+ ///
160
+ /// Callers must ensure that the pointer to the field is in fact a pointer to the specified field,
161
+ /// as opposed to a pointer to another object of the same type.
162
+ ///
163
+ /// # Example
164
+ ///
165
+ ///```
166
+ /// struct Test {
167
+ /// a: u64,
168
+ /// b: u32,
169
+ /// }
170
+ ///
171
+ /// fn test() {
172
+ /// let test = Test{a: 10, b: 20};
173
+ /// let b_ptr = &test.b;
174
+ /// let test_alias = unsafe { container_of!(b_ptr, Test, b) };
175
+ /// // This prints `true`.
176
+ /// println!("{}", core::ptr::eq(&test, test_alias));
177
+ /// }
178
+ ///```
179
+ ///
180
+ #[ macro_export]
181
+ macro_rules! container_of {
182
+ ( $ptr: expr, $type: ty, $( $f: tt) * ) => { {
183
+ let offset = $crate:: offset_of!( $type, $( $f) * ) ;
184
+ ( $ptr as * const _ as * const u8 ) . offset( -offset) as * const $type
185
+ } }
186
+ }
187
+
143
188
#[ global_allocator]
144
189
static ALLOCATOR : allocator:: KernelAllocator = allocator:: KernelAllocator ;
0 commit comments