Skip to content

Commit 20dc3a3

Browse files
committed
rust: add the container_of macro
This is the rust version of the macro with the same name in C. It produces a raw pointer to an outer type from a pointer to an inner field. Signed-off-by: Wedson Almeida Filho <walmeida@microsoft.com>
1 parent 9f2184d commit 20dc3a3

2 files changed

Lines changed: 33 additions & 1 deletion

File tree

rust/kernel/lib.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#![feature(dispatch_from_dyn)]
1818
#![feature(impl_trait_in_assoc_type)]
1919
#![feature(new_uninit)]
20+
#![feature(offset_of)]
2021
#![feature(receiver_trait)]
2122
#![feature(unsize)]
2223

@@ -118,6 +119,37 @@ impl ThisModule {
118119
}
119120
}
120121

122+
/// Produces a pointer to an object from a pointer to one of its fields.
123+
///
124+
/// # Safety
125+
///
126+
/// Callers must ensure that the pointer to the field is in fact a pointer to the specified field,
127+
/// as opposed to a pointer to another object of the same type. If this condition is not met,
128+
/// any dereference of the resulting pointer is UB.
129+
///
130+
/// # Examples
131+
///
132+
/// ```
133+
/// # use kernel::container_of;
134+
/// struct Test {
135+
/// a: u64,
136+
/// b: u32,
137+
/// }
138+
///
139+
/// let test = Test { a: 10, b: 20 };
140+
/// let b_ptr = &test.b;
141+
/// let test_alias = container_of!(b_ptr, Test, b);
142+
/// assert!(core::ptr::eq(&test, test_alias));
143+
/// ```
144+
#[macro_export]
145+
macro_rules! container_of {
146+
($ptr:expr, $type:ty, $($f:tt)*) => {{
147+
let ptr = $ptr as *const _ as *const u8;
148+
let offset = ::core::mem::offset_of!($type, $($f)*) as isize;
149+
ptr.wrapping_offset(-offset) as *const $type
150+
}}
151+
}
152+
121153
#[cfg(not(any(testlib, test)))]
122154
#[panic_handler]
123155
fn panic(info: &core::panic::PanicInfo<'_>) -> ! {

scripts/Makefile.build

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ $(obj)/%.lst: $(src)/%.c FORCE
262262
# Compile Rust sources (.rs)
263263
# ---------------------------------------------------------------------------
264264

265-
rust_allowed_features := new_uninit,impl_trait_in_assoc_type
265+
rust_allowed_features := new_uninit,impl_trait_in_assoc_type,offset_of
266266

267267
# `--out-dir` is required to avoid temporaries being created by `rustc` in the
268268
# current working directory, which may be not accessible in the out-of-tree

0 commit comments

Comments
 (0)