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