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