Skip to content

Instantly share code, notes, and snippets.

@Blei
Created February 10, 2013 12:57
Show Gist options
  • Save Blei/4749513 to your computer and use it in GitHub Desktop.
Save Blei/4749513 to your computer and use it in GitHub Desktop.
extern mod std;
use option::{Option, Some, None};
macro_rules! offset_of(($T:ty, $field:ident) => (
unsafe {
let x: *$T = ptr::null();
ptr::to_uint(&(*x).$field)
}))
macro_rules! container_of(($p:expr, $T:ty, $field:ident) => (
unsafe {
let o = offset_of!($T, $field);
let p2: *$T = (ptr::to_uint($p) - o) as *$T;
&(*p2)
}))
struct Link {
mut next: Option<@Link>,
mut prev: Option<@Link>
}
fn link_init(l: @Link) {
l.next = Some(l);
l.prev = Some(l);
}
#[test]
fn test_offset_of() {
assert(offset_of!(Link, next) == 0);
assert(offset_of!(Link, prev) == 16);
}
#[test]
fn test_container_of() {
struct Wrapper {
foo: int,
l: Link
};
let w = Wrapper {foo: 1, l: Link {mut next: None, mut prev: None}};
let my_l: &Link = &w.l;
let w2: &Wrapper = container_of!(my_l, Wrapper, l);
let my_prev = &w.l.prev;
let w3 = container_of!(container_of!(my_prev, Link, prev), Wrapper, l);
assert(ptr::to_uint(w2) == ptr::to_uint(&w));
assert(ptr::to_uint(w3) == ptr::to_uint(&w));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment