1#[macro_export]
25macro_rules! size_of_field {
26 ($type_name:ty, $($field:ident).+) => {{
27 const fn size_of_pointee<T>(_val: *const T) -> usize {
28 std::mem::size_of::<T>()
29 }
30 const fn compute() -> usize {
31 let p = ::std::mem::MaybeUninit::<$type_name>::uninit();
32 size_of_pointee(unsafe { &raw const (*p.as_ptr()) . $($field).+ })
39 }
40 const size: usize = compute();
41 size
42 }};
43}
44
45#[macro_export]
59macro_rules! check_same_layout {
60 {} => {};
61 {
62 $type_name1:ty = $type_name2:ty
63 {
64 $(
65 $($field1:ident).+ => $($field2:ident).+
66 ),*
67 $(,)?
68 }
69 $($token:tt)*
70 } => {
71 $crate::__static_assertions::assert_eq_size!($type_name1, $type_name2);
72 $(
73 $crate::__static_assertions::const_assert_eq!(
74 std::mem::offset_of!($type_name1, $($field1).+),
75 std::mem::offset_of!($type_name2, $($field2).+)
76 );
77 )*
78 $crate::check_same_layout! { $($token)* }
79 };
80}
81
82#[macro_export]
96macro_rules! check_arch_independent_layout {
97 {} => {};
98 {
99 $type_name:ident {
100 $( $($field:ident).+ ),*
101 $(,)?
102 }
103 $($token:tt)*
104 }=> {
105 $crate::check_same_layout! {
106 $crate::$type_name = $crate::arch32::$type_name {
107 $(
108 $($field).+ => $($field).+,
109 )*
110 }
111 }
112 $crate::check_arch_independent_layout! { $($token)* }
113 };
114}
115
116#[macro_export]
130macro_rules! check_arch_independent_same_layout {
131 {} => {};
132 {
133 $type_name1:ty = $type_name2:ident
134 {
135 $(
136 $($field1:ident).+ => $($field2:ident).+
137 ),*
138 $(,)?
139 }
140 $($token:tt)*
141 } => {
142 $crate::check_same_layout! {
143 $type_name1 = $crate::$type_name2
144 {
145 $($($field1).+ => $($field2).+,)*
146 }
147 }
148 $crate::check_same_layout! {
149 $type_name1 = $crate::arch32::$type_name2
150 {
151 $($($field1).+ => $($field2).+,)*
152 }
153 }
154 $crate::check_arch_independent_same_layout! { $($token)* }
155 };
156}
157
158#[macro_export]
164macro_rules! translate_data {
165 {} => {};
166 {
167 $(#[$meta:meta])*
168 BidiFrom<$type_name1:ty, $type_name2:ty> {
169 $(
170 $field1:ident = $field2:ident;
171 )*
172 $(..$($d1:expr)?, $($d2:expr)?)?
173 }
174 $($token:tt)*
175 } => {
176 $crate::translate_data! {
177 $(#[$meta])*
178 From<$type_name1> for $type_name2 {
179 $( $field2 = $field1; )*
180 $($(..$d2)?)?
181 }
182 $(#[$meta])*
183 From<$type_name2> for $type_name1 {
184 $( $field1 = $field2; )*
185 $($(..$d1)?)?
186 }
187 }
188 $crate::translate_data! { $($token)* }
189 };
190 {
191 $(#[$meta:meta])*
192 BidiTryFrom<$type_name1:ty, $type_name2:ty> {
193 $(
194 $field1:ident = $field2:ident;
195 )*
196 $(..$($d1:expr)?, $($d2:expr)?)?
197 }
198 $($token:tt)*
199 } => {
200 $crate::translate_data! {
201 $(#[$meta])*
202 TryFrom<$type_name1> for $type_name2 {
203 $( $field2 = $field1; )*
204 $($(..$d2)?)?
205 }
206 $(#[$meta])*
207 TryFrom<$type_name2> for $type_name1 {
208 $( $field1 = $field2; )*
209 $($(..$d1)?)?
210 }
211 }
212 $crate::translate_data! { $($token)* }
213 };
214 {
215 $(#[$meta:meta])*
216 From<$type_name1:ty> for $type_name2:ty {
217 $(
218 $field2:ident = $field1:ident;
219 )*
220 $(..$d:expr)?
221 }
222 $($token:tt)*
223 } => {
224 $(#[$meta])*
225 impl From<$type_name1> for $type_name2 {
226 fn from(src: $type_name1) -> Self {
227 Self {
228 $( $field2: src.$field1.into(), )*
229 $(..$d)?
230 }
231 }
232 }
233 $crate::translate_data! { $($token)* }
234 };
235 {
236 $(#[$meta:meta])*
237 TryFrom<$type_name1:ty> for $type_name2:ty {
238 $(
239 $field2:ident = $field1:ident $( ( $field1_default:expr ))?;
240 )*
241 $(..$d:expr)?
242 }
243 $($token:tt)*
244 } => {
245 $(#[$meta])*
246 impl TryFrom<$type_name1> for $type_name2 {
247 type Error = ();
248 fn try_from(src: $type_name1) -> Result<Self, ()> {
249 Ok(Self {
250 $( $field2: $crate::translate_data_expr!( src.$field1 $( ( $field1_default ) )? ), )*
251 $(..$d)?
252 })
253 }
254 }
255 $crate::translate_data! { $($token)* }
256 };
257}
258
259#[macro_export]
260macro_rules! translate_data_expr {
261 ( $src:ident . $field:ident ) => {
262 $src.$field.try_into().map_err(|_| ())?
263 };
264 ( $src:ident . $field:ident ( $field1_default:expr ) ) => {
265 $src.$field.try_into().unwrap_or($field1_default)
266 };
267}
268
269#[macro_export]
276macro_rules! arch_translate_data {
277 {} => {};
278 {
279 BidiFrom<$type_name:ident> {
280 $( $field:ident ),+
281 $(,)?
282 }
283 $($token:tt)*
284 } => {
285 $crate::arch_translate_data! {
286 TryFrom64<$type_name> {
287 $(
288 $field,
289 )*
290 }
291 From32<$type_name> {
292 $(
293 $field,
294 )*
295 }
296 }
297 $crate::arch_translate_data! { $($token)* }
298 };
299 {
300 TryFrom64<$type_name:ident> {
301 $( $field:ident ),+
302 $(,)?
303 }
304 $($token:tt)*
305 } => {
306 $crate::translate_data! {
307 #[cfg(target_arch = "aarch64")]
308 TryFrom<$crate::$type_name> for $crate::arch32::$type_name {
309 $(
310 $field = $field;
311 )*
312 ..Default::default()
313 }
314 }
315 $crate::arch_translate_data! { $($token)* }
316 };
317 {
318 From32<$type_name:ident> {
319 $( $field:ident ),+
320 $(,)?
321 }
322 $($token:tt)*
323 } => {
324 $crate::translate_data! {
325 #[cfg(target_arch = "aarch64")]
326 From<$crate::arch32::$type_name> for $crate::$type_name {
327 $(
328 $field = $field;
329 )*
330 ..Default::default()
331 }
332 }
333 $crate::arch_translate_data! { $($token)* }
334 };
335}
336
337#[macro_export]
339macro_rules! arch_map_data {
340 {} => {};
341 {
342 BidiTryFrom<$type_name1:ty, $type_name2:ident> {
343 $(
344 $field1:ident = $field2:ident;
345 )*
346 $(..$d:expr)?
347 }
348 $($token:tt)*
349 } => {
350 $crate::translate_data! {
351 BidiTryFrom<$type_name1, $crate::$type_name2> {
352 $(
353 $field1 = $field2;
354 )*
355 ..$($d)?, Default::default()
356 }
357 #[cfg(target_arch = "aarch64")]
358 BidiTryFrom<$type_name1, $crate::arch32::$type_name2> {
359 $(
360 $field1 = $field2;
361 )*
362 ..$($d)?, Default::default()
363 }
364 }
365 $crate::arch_map_data! { $($token)* }
366 };
367}