1 | //! Macros for low-level memory manipulation. |
2 | |
3 | /// Make a tuple of the addresses of some of a struct's fields. |
4 | /// |
5 | /// This is useful when you are transmuting between struct types |
6 | /// and would like an additional dynamic check that the layouts |
7 | /// match. It's difficult to make such an assertion statically |
8 | /// in Rust at present. |
9 | /// |
10 | /// # Example |
11 | /// |
12 | /// ``` |
13 | /// # #[macro_use ] extern crate mac; |
14 | /// use std::mem; |
15 | /// |
16 | /// # fn main() { |
17 | /// struct Foo { x: i32, y: i32 } |
18 | /// struct Bar { x: u32, y: u32 } |
19 | /// |
20 | /// let foo = Foo { x: 3, y: 4 }; |
21 | /// let old_addrs = addrs_of!(foo => x, y); |
22 | /// |
23 | /// let bar = unsafe { |
24 | /// mem::transmute::<&Foo, &Bar>(&foo) |
25 | /// }; |
26 | /// let new_addrs = addrs_of!(bar => x, y); |
27 | /// assert_eq!(old_addrs, new_addrs); |
28 | /// |
29 | /// assert_eq!(bar.x, 3); |
30 | /// assert_eq!(bar.y, 4); |
31 | /// # } |
32 | /// ``` |
33 | #[macro_export ] |
34 | macro_rules! addrs_of { |
35 | ($obj:expr => $($field:ident),+) => { |
36 | ( // make a tuple |
37 | $( |
38 | unsafe { |
39 | ::std::mem::transmute::<_, usize>(&$obj.$field) |
40 | } |
41 | ),+ |
42 | ) |
43 | } |
44 | } |
45 | |