Skip to content

Commit

Permalink
Add tests and change return type to *const
Browse files Browse the repository at this point in the history
  • Loading branch information
Amanieu committed Aug 16, 2019
1 parent 1b98c2f commit f8caaff
Showing 1 changed file with 63 additions and 5 deletions.
68 changes: 63 additions & 5 deletions src/container_of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@
///
/// fn main() {
/// let container = Foo { a: 1, b: 2, c: [3; 5] };
/// let field = &container.b;
/// let container2: *const Foo = unsafe { container_of!(field, Foo, b) };
/// let field_ptr = &container.b;
/// let container2: *const Foo = unsafe { container_of!(field_ptr, Foo, b) };
/// assert_eq!(&container as *const Foo, container2);
/// }
/// ```
Expand All @@ -31,12 +31,70 @@ macro_rules! container_of {
let ptr = $ptr as *const _;
if false {
// Ensure that the pointer has the correct type.
let $container { $field: f, .. };
f = *ptr;
let $container { $field: _f, .. };
_f = *ptr;
}

// We don't use .sub because we need to support older Rust versions.
(ptr as *const u8).offset((offset_of!($container, $field) as isize).wrapping_neg())
as *mut $container
as *const $container
}};
}

#[cfg(test)]
mod tests {
#[test]
fn simple() {
#[repr(C)]
struct Foo {
a: u32,
b: [u8; 2],
c: i64,
}

let x = Foo {
a: 0,
b: [0; 2],
c: 0,
};
unsafe {
assert_eq!(container_of!(&x.a, Foo, a), &x as *const _);
assert_eq!(container_of!(&x.b, Foo, b), &x as *const _);
assert_eq!(container_of!(&x.c, Foo, c), &x as *const _);
}
}

#[test]
#[cfg(not(miri))] // this creates unaligned references
fn simple_packed() {
#[repr(C, packed)]
struct Foo {
a: u32,
b: [u8; 2],
c: i64,
}

let x = Foo {
a: 0,
b: [0; 2],
c: 0,
};
unsafe {
assert_eq!(container_of!(&x.a, Foo, a), &x as *const _);
assert_eq!(container_of!(&x.b, Foo, b), &x as *const _);
assert_eq!(container_of!(&x.c, Foo, c), &x as *const _);
}
}

#[test]
fn tuple_struct() {
#[repr(C)]
struct Tup(i32, i32);

let x = Tup(0, 0);
unsafe {
assert_eq!(container_of!(&x.0, Tup, 0), &x as *const _);
assert_eq!(container_of!(&x.1, Tup, 1), &x as *const _);
}
}
}

0 comments on commit f8caaff

Please sign in to comment.