1#[doc(hidden)]
24#[macro_export]
25macro_rules! _memoffset__compile_error {
26 ($($inner:tt)*) => {
27 compile_error! { $($inner)* }
28 }
29}
30
31#[macro_export(local_inner_macros)]
88macro_rules! span_of {
89 (@helper $root:ident, [] ..=) => {
90 _memoffset__compile_error!("Expected a range, found '..='")
91 };
92 (@helper $root:ident, [] ..) => {
93 _memoffset__compile_error!("Expected a range, found '..'")
94 };
95 (@helper $root:ident, $parent:path, [] ..) => {{
97 ($root as usize,
98 $root as usize + $crate::__priv::size_of_pointee($root))
99 }};
100 (@helper $root:ident, $parent:path, [] ..= $end:tt) => {{
101 let end = raw_field!($root, $parent, $end);
102 ($root as usize, end as usize + $crate::__priv::size_of_pointee(end))
103 }};
104 (@helper $root:ident, $parent:path, [] .. $end:tt) => {{
105 ($root as usize, raw_field!($root, $parent, $end) as usize)
106 }};
107 (@helper $root:ident, $parent:path, # $begin:tt [] ..= $end:tt) => {{
109 let begin = raw_field!($root, $parent, $begin);
110 let end = raw_field!($root, $parent, $end);
111 (begin as usize, end as usize + $crate::__priv::size_of_pointee(end))
112 }};
113 (@helper $root:ident, $parent:path, # $begin:tt [] .. $end:tt) => {{
114 (raw_field!($root, $parent, $begin) as usize,
115 raw_field!($root, $parent, $end) as usize)
116 }};
117 (@helper $root:ident, $parent:path, # $begin:tt [] ..) => {{
119 (raw_field!($root, $parent, $begin) as usize,
120 $root as usize + $crate::__priv::size_of_pointee($root))
121 }};
122 (@helper $root:ident, $parent:path, # $begin:tt [] ..=) => {{
123 _memoffset__compile_error!(
124 "Found inclusive range to the end of a struct. Did you mean '..' instead of '..='?")
125 }};
126 (@helper $root:ident, $parent:path, # $field:tt []) => {{
128 let field = raw_field!($root, $parent, $field);
129 (field as usize, field as usize + $crate::__priv::size_of_pointee(field))
130 }};
131 (@helper $root:ident, $parent:path, $(# $begin:tt)+ [] $tt:tt $($rest:tt)*) => {{
133 span_of!(@helper $root, $parent, $(#$begin)* #$tt [] $($rest)*)
134 }};
135 (@helper $root:ident, $parent:path, [] $tt:tt $($rest:tt)*) => {{
136 span_of!(@helper $root, $parent, #$tt [] $($rest)*)
137 }};
138
139 ($sty:path, $($exp:tt)+) => ({
141 _memoffset__let_base_ptr!(root, $sty);
143 let base = root as usize;
144 let (begin, end) = span_of!(@helper root, $sty, [] $($exp)*);
145 begin-base..end-base
146 });
147}
148
149#[cfg(test)]
150mod tests {
151 use core::mem;
152
153 #[test]
154 fn span_simple() {
155 #[repr(C)]
156 struct Foo {
157 a: u32,
158 b: [u8; 2],
159 c: i64,
160 }
161
162 assert_eq!(span_of!(Foo, a), 0..4);
163 assert_eq!(span_of!(Foo, b), 4..6);
164 assert_eq!(span_of!(Foo, c), 8..8 + 8);
165 }
166
167 #[test]
168 #[cfg_attr(miri, ignore)] fn span_simple_packed() {
170 #[repr(C, packed)]
171 struct Foo {
172 a: u32,
173 b: [u8; 2],
174 c: i64,
175 }
176
177 assert_eq!(span_of!(Foo, a), 0..4);
178 assert_eq!(span_of!(Foo, b), 4..6);
179 assert_eq!(span_of!(Foo, c), 6..6 + 8);
180 }
181
182 #[test]
183 fn span_forms() {
184 #[repr(C)]
185 struct Florp {
186 a: u32,
187 }
188
189 #[repr(C)]
190 struct Blarg {
191 x: u64,
192 y: [u8; 56],
193 z: Florp,
194 egg: [[u8; 4]; 5],
195 }
196
197 assert_eq!(0..8, span_of!(Blarg, x));
199 assert_eq!(64..68, span_of!(Blarg, z));
200 assert_eq!(68..mem::size_of::<Blarg>(), span_of!(Blarg, egg));
201
202 assert_eq!(8..64, span_of!(Blarg, y..z));
203 assert_eq!(0..64, span_of!(Blarg, x..=y));
204 }
205
206 #[test]
207 fn ig_test() {
208 #[repr(C)]
209 struct Member {
210 foo: u32,
211 }
212
213 #[repr(C)]
214 struct Test {
215 x: u64,
216 y: [u8; 56],
217 z: Member,
218 egg: [[u8; 4]; 4],
219 }
220
221 assert_eq!(span_of!(Test, ..x), 0..0);
222 assert_eq!(span_of!(Test, ..=x), 0..8);
223 assert_eq!(span_of!(Test, ..y), 0..8);
224 assert_eq!(span_of!(Test, ..=y), 0..64);
225 assert_eq!(span_of!(Test, ..z), 0..64);
226 assert_eq!(span_of!(Test, ..=z), 0..68);
227 assert_eq!(span_of!(Test, ..egg), 0..68);
228 assert_eq!(span_of!(Test, ..=egg), 0..84);
229 assert_eq!(span_of!(Test, ..), 0..mem::size_of::<Test>());
230 assert_eq!(
231 span_of!(Test, x..),
232 offset_of!(Test, x)..mem::size_of::<Test>()
233 );
234 assert_eq!(
235 span_of!(Test, y..),
236 offset_of!(Test, y)..mem::size_of::<Test>()
237 );
238
239 assert_eq!(
240 span_of!(Test, z..),
241 offset_of!(Test, z)..mem::size_of::<Test>()
242 );
243 assert_eq!(
244 span_of!(Test, egg..),
245 offset_of!(Test, egg)..mem::size_of::<Test>()
246 );
247 assert_eq!(
248 span_of!(Test, x..y),
249 offset_of!(Test, x)..offset_of!(Test, y)
250 );
251 assert_eq!(
252 span_of!(Test, x..=y),
253 offset_of!(Test, x)..offset_of!(Test, y) + mem::size_of::<[u8; 56]>()
254 );
255 }
256}