/rust/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.191/src/macros.rs
Line | Count | Source |
1 | | /// A macro for defining #[cfg] if-else statements. |
2 | | /// |
3 | | /// This is similar to the `if/elif` C preprocessor macro by allowing definition of a cascade of |
4 | | /// `#[cfg]` cases, emitting the implementation which matches first. |
5 | | /// |
6 | | /// This allows you to conveniently provide a long list #[cfg]'d blocks of code without having to |
7 | | /// rewrite each clause multiple times. |
8 | | macro_rules! cfg_if { |
9 | | // match if/else chains with a final `else` |
10 | | ($( |
11 | | if #[cfg($($meta:meta),*)] { $($it:item)* } |
12 | | ) else * else { |
13 | | $($it2:item)* |
14 | | }) => { |
15 | | cfg_if! { |
16 | | @__items |
17 | | () ; |
18 | | $( ( ($($meta),*) ($($it)*) ), )* |
19 | | ( () ($($it2)*) ), |
20 | | } |
21 | | }; |
22 | | |
23 | | // match if/else chains lacking a final `else` |
24 | | ( |
25 | | if #[cfg($($i_met:meta),*)] { $($i_it:item)* } |
26 | | $( |
27 | | else if #[cfg($($e_met:meta),*)] { $($e_it:item)* } |
28 | | )* |
29 | | ) => { |
30 | | cfg_if! { |
31 | | @__items |
32 | | () ; |
33 | | ( ($($i_met),*) ($($i_it)*) ), |
34 | | $( ( ($($e_met),*) ($($e_it)*) ), )* |
35 | | ( () () ), |
36 | | } |
37 | | }; |
38 | | |
39 | | // Internal and recursive macro to emit all the items |
40 | | // |
41 | | // Collects all the negated `cfg`s in a list at the beginning and after the |
42 | | // semicolon is all the remaining items |
43 | | (@__items ($($not:meta,)*) ; ) => {}; |
44 | | (@__items ($($not:meta,)*) ; ( ($($m:meta),*) ($($it:item)*) ), |
45 | | $($rest:tt)*) => { |
46 | | // Emit all items within one block, applying an appropriate #[cfg]. The |
47 | | // #[cfg] will require all `$m` matchers specified and must also negate |
48 | | // all previous matchers. |
49 | | cfg_if! { @__apply cfg(all($($m,)* not(any($($not),*)))), $($it)* } |
50 | | |
51 | | // Recurse to emit all other items in `$rest`, and when we do so add all |
52 | | // our `$m` matchers to the list of `$not` matchers as future emissions |
53 | | // will have to negate everything we just matched as well. |
54 | | cfg_if! { @__items ($($not,)* $($m,)*) ; $($rest)* } |
55 | | }; |
56 | | |
57 | | // Internal macro to Apply a cfg attribute to a list of items |
58 | | (@__apply $m:meta, $($it:item)*) => { |
59 | | $(#[$m] $it)* |
60 | | }; |
61 | | } |
62 | | |
63 | | /// Create an internal crate prelude with `core` reexports and common types. |
64 | | macro_rules! prelude { |
65 | | () => { |
66 | | mod types; |
67 | | |
68 | | /// Frequently-used types that are available on all platforms |
69 | | /// |
70 | | /// We need to reexport the core types so this works with `rust-dep-of-std`. |
71 | | mod prelude { |
72 | | // Exports from `core` |
73 | | #[allow(unused_imports)] |
74 | | pub(crate) use core::clone::Clone; |
75 | | #[allow(unused_imports)] |
76 | | pub(crate) use core::cmp::{ |
77 | | Eq, |
78 | | PartialEq, |
79 | | }; |
80 | | #[allow(unused_imports)] |
81 | | pub(crate) use core::default::Default; |
82 | | #[allow(unused_imports)] |
83 | | pub(crate) use core::iter::Iterator; |
84 | | #[allow(unused_imports)] |
85 | | pub(crate) use core::marker::{ |
86 | | Copy, |
87 | | Send, |
88 | | Sync, |
89 | | }; |
90 | | #[allow(unused_imports)] |
91 | | pub(crate) use core::option::Option::{ |
92 | | self, |
93 | | None, |
94 | | Some, |
95 | | }; |
96 | | #[allow(unused_imports)] |
97 | | pub(crate) use core::prelude::v1::derive; |
98 | | #[allow(unused_imports)] |
99 | | pub(crate) use core::{ |
100 | | assert, |
101 | | cfg, |
102 | | compile_error, |
103 | | debug_assert, |
104 | | fmt, |
105 | | hash, |
106 | | iter, |
107 | | mem, |
108 | | panic, |
109 | | ptr, |
110 | | unimplemented, |
111 | | }; |
112 | | |
113 | | #[allow(unused_imports)] |
114 | | pub(crate) use fmt::Debug; |
115 | | #[allow(unused_imports)] |
116 | | pub(crate) use mem::{ |
117 | | align_of, |
118 | | align_of_val, |
119 | | size_of, |
120 | | size_of_val, |
121 | | }; |
122 | | |
123 | | #[allow(unused_imports)] |
124 | | #[cfg(any(target_os = "linux", target_os = "android", target_os = "l4re"))] |
125 | | pub(crate) use crate::types::u32_cast_ioctl; |
126 | | #[allow(unused_imports)] |
127 | | pub(crate) use crate::types::{ |
128 | | cstr, |
129 | | replace_array_items, |
130 | | u16_cast_short, |
131 | | u32_cast_int, |
132 | | u32_cast_long, |
133 | | u8_slice_cast_char_slice, |
134 | | ulong_cast_int, |
135 | | ulong_cast_uint, |
136 | | CEnumRepr, |
137 | | Padding, |
138 | | }; |
139 | | // Commonly used types defined in this crate |
140 | | #[allow(unused_imports)] |
141 | | pub(crate) use crate::{ |
142 | | c_char, |
143 | | c_double, |
144 | | c_float, |
145 | | c_int, |
146 | | c_long, |
147 | | c_longlong, |
148 | | c_short, |
149 | | c_uchar, |
150 | | c_uint, |
151 | | c_ulong, |
152 | | c_ulonglong, |
153 | | c_ushort, |
154 | | c_void, |
155 | | intptr_t, |
156 | | size_t, |
157 | | ssize_t, |
158 | | uintptr_t, |
159 | | }; |
160 | | } |
161 | | }; |
162 | | } |
163 | | |
164 | | /// Implement `Clone`, `Copy`, and `Debug` for one or more structs, as well as `PartialEq`, `Eq`, |
165 | | /// and `Hash` if the `extra_traits` feature is enabled. |
166 | | /// |
167 | | /// Also mark the type with `repr(C)`. |
168 | | /// |
169 | | /// Use [`s_no_extra_traits`] for structs where the `extra_traits` feature does not make sense, and |
170 | | /// for unions. |
171 | | macro_rules! s { |
172 | | ($( |
173 | | $(#[$attr:meta])* |
174 | | $pub:vis $t:ident $i:ident { $($field:tt)* } |
175 | | )*) => ($( |
176 | | s!(it: $(#[$attr])* $pub $t $i { $($field)* }); |
177 | | )*); |
178 | | |
179 | | (it: $(#[$attr:meta])* $pub:vis union $i:ident { $($field:tt)* }) => ( |
180 | | compile_error!("unions cannot derive extra traits, use s_no_extra_traits instead"); |
181 | | ); |
182 | | |
183 | | (it: $(#[$attr:meta])* $pub:vis struct $i:ident { $($field:tt)* }) => ( |
184 | | #[repr(C)] |
185 | | #[::core::prelude::v1::derive( |
186 | | ::core::clone::Clone, |
187 | | ::core::marker::Copy, |
188 | | ::core::fmt::Debug, |
189 | | )] |
190 | | #[cfg_attr( |
191 | | feature = "extra_traits", |
192 | | ::core::prelude::v1::derive( |
193 | | ::core::cmp::PartialEq, |
194 | | ::core::cmp::Eq, |
195 | | ::core::hash::Hash, |
196 | | ) |
197 | | )] |
198 | | #[allow(deprecated)] |
199 | | $(#[$attr])* |
200 | | $pub struct $i { $($field)* } |
201 | | ); |
202 | | } |
203 | | |
204 | | /// Implement `Clone`, `Copy`, and `Debug` for a tuple struct, as well as `PartialEq`, `Eq`, and |
205 | | /// `Hash` if the `extra_traits` feature is enabled. |
206 | | /// |
207 | | /// Unlike `s!`, this does *not* mark the type with `repr(C)`. Users should provide their own |
208 | | /// `repr` attribute via `$attr` as necessary. |
209 | | macro_rules! s_paren { |
210 | | ($( |
211 | | $(#[$attr:meta])* |
212 | | $pub:vis struct $i:ident ( $($field:tt)* ); |
213 | | )*) => ($( |
214 | | #[::core::prelude::v1::derive( |
215 | | ::core::clone::Clone, |
216 | | ::core::marker::Copy, |
217 | | ::core::fmt::Debug, |
218 | | )] |
219 | | #[cfg_attr( |
220 | | feature = "extra_traits", |
221 | | ::core::prelude::v1::derive( |
222 | | ::core::cmp::PartialEq, |
223 | | ::core::cmp::Eq, |
224 | | ::core::hash::Hash, |
225 | | ) |
226 | | )] |
227 | | $(#[$attr])* |
228 | | $pub struct $i ( $($field)* ); |
229 | | )*); |
230 | | } |
231 | | |
232 | | /// Implement `Clone`, `Copy`, and `Debug` for one or more structs/unions, but exclude `PartialEq`, |
233 | | /// `Eq`, and `Hash`. |
234 | | /// |
235 | | /// Also mark the type with `repr(C)`. |
236 | | /// |
237 | | /// Most structs will prefer to use [`s`]. |
238 | | macro_rules! s_no_extra_traits { |
239 | | ($( |
240 | | $(#$attr:tt)* |
241 | | $pub:vis $t:ident $i:ident { $($field:tt)* } |
242 | | )*) => ($( |
243 | | s_no_extra_traits!(it: $(#$attr)* $pub $t $i { $($field)* }); |
244 | | )*); |
245 | | |
246 | | (it: $(#$attr:tt)* $pub:vis union $i:ident { $($field:tt)* }) => ( |
247 | | union_with_debug! { |
248 | | $(#$attr)* $pub union $i { $($field)* } |
249 | | } |
250 | | ); |
251 | | |
252 | | (it: $(#$attr:tt)* $pub:vis struct $i:ident { $($field:tt)* }) => ( |
253 | | #[repr(C)] |
254 | | #[::core::prelude::v1::derive( |
255 | | ::core::clone::Clone, |
256 | | ::core::marker::Copy, |
257 | | ::core::fmt::Debug, |
258 | | )] |
259 | | $(#$attr)* |
260 | | $pub struct $i { $($field)* } |
261 | | ); |
262 | | } |
263 | | |
264 | | /// Like [`s`], but (1) generates a `Default` impl for every struct in the block, and (2) adds a |
265 | | /// private field to the struct to replicate the effects of the `non_exhaustive` attribute while |
266 | | /// rust-lang/rust#132699 gets sorted out. |
267 | | /// |
268 | | /// To opt out of having the private field added, annotate the struct with an `exhaustive` |
269 | | /// attribute, as in: |
270 | | /// |
271 | | /// ```ignore |
272 | | /// s2! { |
273 | | /// #[exhaustive] |
274 | | /// struct Something { |
275 | | /// ... |
276 | | /// } |
277 | | /// } |
278 | | /// ``` |
279 | | /// |
280 | | /// See [`custom_struct`] for details. |
281 | | macro_rules! s2 { |
282 | | ($( |
283 | | $(#$attr:tt)* |
284 | | $pub:vis $t:ident $i:ident { $($field:tt)* } |
285 | | )*) => ($( |
286 | | s2!(it: $(#$attr)* $pub $t $i { $($field)* }); |
287 | | )*); |
288 | | |
289 | | (it: $(#$attr:tt)* $pub:vis union $i:ident { $($field:tt)* }) => ( |
290 | | compile_error!( |
291 | | "unions cannot derive extra traits, use `s_no_extra_traits2` \ |
292 | | instead" |
293 | | ); |
294 | | ); |
295 | | |
296 | | (it: $(#$attr:tt)* $pub:vis struct $i:ident { $($field:tt)* }) => ( |
297 | | custom_struct! { |
298 | | attrs: { |
299 | | #[repr(C)] |
300 | | #[::core::prelude::v1::derive( |
301 | | ::core::clone::Clone, |
302 | | ::core::marker::Copy, |
303 | | ::core::fmt::Debug, |
304 | | )] |
305 | | #[cfg_attr( |
306 | | feature = "extra_traits", |
307 | | ::core::prelude::v1::derive( |
308 | | ::core::cmp::PartialEq, |
309 | | ::core::cmp::Eq, |
310 | | ::core::hash::Hash, |
311 | | ) |
312 | | )] |
313 | | #[allow(deprecated)] |
314 | | } |
315 | | $(#$attr)* $pub struct $i { $($field)* } |
316 | | } |
317 | | ); |
318 | | } |
319 | | |
320 | | /// Like [`s_no_extra_traits`], but (1) generates a `Default` impl for every struct in the block, |
321 | | /// and (2) adds a private field to replicate the effects of the built-in `non_exhaustive` attribute |
322 | | /// while rust-lang/rust#132699 gets sorted out. |
323 | | /// |
324 | | /// Unions are emitted just like `s_no_extra_traits!` does, with no `Default`. A struct field of |
325 | | /// union type supplies its own default via `#[custom_default(...)]`. |
326 | | /// |
327 | | /// To opt out of having the private field added, annotate the struct with an `exhaustive` |
328 | | /// attribute, as in: |
329 | | /// |
330 | | /// ```ignore |
331 | | /// s_no_extra_traits2! { |
332 | | /// #[exhaustive] |
333 | | /// struct Something { |
334 | | /// ... |
335 | | /// } |
336 | | /// } |
337 | | /// ``` |
338 | | macro_rules! s_no_extra_traits2 { |
339 | | ($( |
340 | | $(#$attr:tt)* |
341 | | $pub:vis $t:ident $i:ident { $($field:tt)* } |
342 | | )*) => ($( |
343 | | s_no_extra_traits2!(it: $(#$attr)* $pub $t $i { $($field)* }); |
344 | | )*); |
345 | | |
346 | | (it: $(#$attr:tt)* $pub:vis union $i:ident { $($field:tt)* }) => ( |
347 | | union_with_debug! { |
348 | | $(#$attr)* $pub union $i { $($field)* } |
349 | | } |
350 | | ); |
351 | | |
352 | | (it: $(#$attr:tt)* $pub:vis struct $i:ident { $($field:tt)* }) => ( |
353 | | custom_struct! { |
354 | | attrs: { |
355 | | #[repr(C)] |
356 | | #[::core::prelude::v1::derive( |
357 | | ::core::clone::Clone, |
358 | | ::core::marker::Copy, |
359 | | ::core::fmt::Debug, |
360 | | )] |
361 | | } |
362 | | $(#$attr)* $pub struct $i { $($field)* } |
363 | | } |
364 | | ); |
365 | | } |
366 | | |
367 | | /// Emit a union plus its `Debug` impl. |
368 | | /// |
369 | | /// Unions can't derive `Debug`, so it is written out here. Attributes are split like |
370 | | /// [`custom_struct`] does. Everything goes on the union, but only the `cfg`s are repeated on the |
371 | | /// impl, otherwise a union that is configured out leaves an impl behind. |
372 | | macro_rules! union_with_debug { |
373 | | ( |
374 | | $(#$attr:tt)* |
375 | | $vis:vis union $name:ident { $($body:tt)* } |
376 | | ) => { |
377 | | union_with_debug! { |
378 | | @split_attrs, |
379 | | cfg_attrs: { }, |
380 | | other_attrs: { }, |
381 | | remaining_attrs: { $(#$attr)* }, |
382 | | found_default_via_unsafe_zeroed: false, |
383 | | vis: $vis, |
384 | | name: $name, |
385 | | body: { $($body)* }, |
386 | | } |
387 | | }; |
388 | | |
389 | | // a `cfg` also has to gate the impl |
390 | | ( |
391 | | @split_attrs, |
392 | | cfg_attrs: { $($cfg_attrs:tt)* }, |
393 | | other_attrs: { $($other_attrs:tt)* }, |
394 | | remaining_attrs: { |
395 | | #[cfg($($cfg:tt)*)] |
396 | | $($tail:tt)* |
397 | | }, |
398 | | found_default_via_unsafe_zeroed: $found_default:tt, |
399 | | vis: $vis:vis, |
400 | | name: $name:ident, |
401 | | body: { $($body:tt)* }, |
402 | | ) => { |
403 | | union_with_debug! { |
404 | | @split_attrs, |
405 | | cfg_attrs: { $($cfg_attrs)* #[cfg($($cfg)*)] }, |
406 | | other_attrs: { $($other_attrs)* }, |
407 | | remaining_attrs: { $($tail)* }, |
408 | | found_default_via_unsafe_zeroed: $found_default, |
409 | | vis: $vis, |
410 | | name: $name, |
411 | | body: { $($body)* }, |
412 | | } |
413 | | }; |
414 | | |
415 | | // a `cfg` also has to gate the impl |
416 | | ( |
417 | | @split_attrs, |
418 | | cfg_attrs: { $($cfg_attrs:tt)* }, |
419 | | other_attrs: { $($other_attrs:tt)* }, |
420 | | remaining_attrs: { |
421 | | #[unsafe(union_default_via_zeroed)] |
422 | | $($tail:tt)* |
423 | | }, |
424 | | found_default_via_unsafe_zeroed: $found_default:tt, |
425 | | vis: $vis:vis, |
426 | | name: $name:ident, |
427 | | body: { $($body:tt)* }, |
428 | | ) => { |
429 | | union_with_debug! { |
430 | | @split_attrs, |
431 | | cfg_attrs: { $($cfg_attrs)* }, |
432 | | other_attrs: { $($other_attrs)* }, |
433 | | remaining_attrs: { $($tail)* }, |
434 | | found_default_via_unsafe_zeroed: true, |
435 | | vis: $vis, |
436 | | name: $name, |
437 | | body: { $($body)* }, |
438 | | } |
439 | | }; |
440 | | |
441 | | // anything else belongs to the union only |
442 | | ( |
443 | | @split_attrs, |
444 | | cfg_attrs: { $($cfg_attrs:tt)* }, |
445 | | other_attrs: { $($other_attrs:tt)* }, |
446 | | remaining_attrs: { |
447 | | #$other:tt |
448 | | $($tail:tt)* |
449 | | }, |
450 | | found_default_via_unsafe_zeroed: $found_default:tt, |
451 | | vis: $vis:vis, |
452 | | name: $name:ident, |
453 | | body: { $($body:tt)* }, |
454 | | ) => { |
455 | | union_with_debug! { |
456 | | @split_attrs, |
457 | | cfg_attrs: { $($cfg_attrs)* }, |
458 | | other_attrs: { $($other_attrs)* #$other }, |
459 | | remaining_attrs: { $($tail)* }, |
460 | | found_default_via_unsafe_zeroed: $found_default, |
461 | | vis: $vis, |
462 | | name: $name, |
463 | | body: { $($body)* }, |
464 | | } |
465 | | }; |
466 | | |
467 | | // done |
468 | | ( |
469 | | @split_attrs, |
470 | | cfg_attrs: { $($cfg_attrs:tt)* }, |
471 | | other_attrs: { $($other_attrs:tt)* }, |
472 | | remaining_attrs: { }, |
473 | | found_default_via_unsafe_zeroed: $found_default:tt, |
474 | | vis: $vis:vis, |
475 | | name: $name:ident, |
476 | | body: { $($body:tt)* }, |
477 | | ) => { |
478 | | #[repr(C)] |
479 | | #[::core::prelude::v1::derive( |
480 | | ::core::clone::Clone, |
481 | | ::core::marker::Copy, |
482 | | )] |
483 | | $($other_attrs)* |
484 | | $($cfg_attrs)* |
485 | | $vis union $name { $($body)* } |
486 | | |
487 | | $($cfg_attrs)* |
488 | | #[allow(deprecated)] |
489 | | impl ::core::fmt::Debug for $name { |
490 | 0 | fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { |
491 | 0 | f.debug_struct(::core::stringify!($name)).finish_non_exhaustive() |
492 | 0 | } Unexecuted instantiation: <libc::unix::linux_like::linux_l4re_shared::__c_anonymous_ifr_ifru as core::fmt::Debug>::fmt Unexecuted instantiation: <libc::unix::linux_like::linux::gnu::__c_anonymous_ptrace_syscall_info_data as core::fmt::Debug>::fmt Unexecuted instantiation: <libc::unix::linux_like::linux_l4re_shared::__c_anonymous_ifc_ifcu as core::fmt::Debug>::fmt Unexecuted instantiation: <libc::unix::linux_like::linux::iwreq_data as core::fmt::Debug>::fmt Unexecuted instantiation: <libc::unix::linux_like::linux::__c_anonymous_iwreq as core::fmt::Debug>::fmt Unexecuted instantiation: <libc::unix::linux_like::linux::__c_anonymous_ptp_perout_request_1 as core::fmt::Debug>::fmt Unexecuted instantiation: <libc::unix::linux_like::linux::__c_anonymous_ptp_perout_request_2 as core::fmt::Debug>::fmt Unexecuted instantiation: <libc::unix::linux_like::linux::__c_anonymous_xsk_tx_metadata_union as core::fmt::Debug>::fmt Unexecuted instantiation: <libc::new::glibc::sysdeps::unix::linux::bits::types::siginfo_t::__c_anonymous_siginfo_t__si_fields as core::fmt::Debug>::fmt Unexecuted instantiation: <libc::new::linux_uapi::linux::if_packet::tpacket_req_u as core::fmt::Debug>::fmt Unexecuted instantiation: <libc::new::linux_uapi::linux::can::__c_anonymous_sockaddr_can_can_addr as core::fmt::Debug>::fmt Unexecuted instantiation: <libc::new::glibc::sysdeps::unix::linux::bits::types::siginfo_t::__c_anonymous__sigfault__bounds as core::fmt::Debug>::fmt Unexecuted instantiation: <libc::new::linux_uapi::linux::if_packet::tpacket_bd_header_u as core::fmt::Debug>::fmt |
493 | | } |
494 | | |
495 | | emit_union_default_via_unsafe_zeroed! { |
496 | | found_default_via_unsafe_zeroed: $found_default, |
497 | | cfg_attrs: { $($cfg_attrs)* }, |
498 | | name: $name, |
499 | | } |
500 | | }; |
501 | | } |
502 | | |
503 | | /// Add a `Default` impl that is just `mem::zeroed`. |
504 | | macro_rules! emit_union_default_via_unsafe_zeroed { |
505 | | ( |
506 | | found_default_via_unsafe_zeroed: false, |
507 | | cfg_attrs: { $($cfg_attrs:tt)* }, |
508 | | name: $name:ident, |
509 | | ) => { |
510 | | }; |
511 | | |
512 | | ( |
513 | | found_default_via_unsafe_zeroed: true, |
514 | | cfg_attrs: { $($cfg_attrs:tt)* }, |
515 | | name: $name:ident, |
516 | | ) => { |
517 | | $($cfg_attrs)* |
518 | | impl ::core::default::Default for $name { |
519 | | fn default() -> Self { |
520 | | unsafe { ::core::mem::zeroed() } |
521 | | } |
522 | | } |
523 | | }; |
524 | | } |
525 | | |
526 | | /// Emit a struct with the given derive attributes plus a generated `Default` impl. Ensure that the |
527 | | /// record has an additional private field added to replicate `#[non_exhaustive]`, unless it is |
528 | | /// annotated with `#[exhaustive]`. |
529 | | /// |
530 | | /// Fields default to `Default::default()`. A field whose default can't be derived must carry |
531 | | /// `#[custom_default(EXPR)]` as its *first* attribute, and `EXPR` is used instead. |
532 | | /// |
533 | | /// This works by scanning each field for `#[custom_default]` attributes. If one exists, the |
534 | | /// attribute's contents are added to `processed_field_defaults` and will be used in the expansion |
535 | | /// for `Default`. If it does not exist, `Default::default()` is used instead. In either case, the |
536 | | /// field is added to `processed_fields` with `#[custom_default]` stripped if necessary, and |
537 | | /// `custom_struct` is invoked again with the remaining fields. |
538 | | /// |
539 | | /// Attributes are split into `cfg_attrs` and `other_attrs` before the fields are scanned. Both go |
540 | | /// on the struct, but only the `cfg`s are repeated on the `Default` impl. A `cfg` decides whether |
541 | | /// the type exists at all, so without it a configured-out struct leaves an impl behind referring to |
542 | | /// a type that isn't there. |
543 | | /// |
544 | | /// Out of `other_attrs`, we scan for `#[exhaustive]`. If found, we remove it but take into account |
545 | | /// that the record should be expanded _without_ an additional private field. The scan for both |
546 | | /// `cfg` attributes and the (non-existent) `exhaustive` attribute is done in one linear pass. |
547 | | macro_rules! custom_struct { |
548 | | // entry; `attrs` is the attribute block the caller wants on the struct |
549 | | // (repr, derives, etc.), which is merged with the struct's own attributes. |
550 | | ( |
551 | | attrs: { $($attrs:tt)* } |
552 | | $(#$attr:tt)* |
553 | | $vis:vis struct $name:ident { $($body:tt)* } |
554 | | ) => { |
555 | | custom_struct! { |
556 | | @split_attrs, |
557 | | cfg_attrs: { }, |
558 | | other_attrs: { }, |
559 | | remaining_attrs: { $($attrs)* $(#$attr)* }, |
560 | | found_exhaustive_attr: false, |
561 | | vis: $vis, |
562 | | name: $name, |
563 | | body: { $($body)* }, |
564 | | } |
565 | | }; |
566 | | |
567 | | // a `cfg` also has to gate the impl |
568 | | ( |
569 | | @split_attrs, |
570 | | cfg_attrs: { $($cfg_attrs:tt)* }, |
571 | | other_attrs: { $($other_attrs:tt)* }, |
572 | | remaining_attrs: { |
573 | | #[cfg($($cfg:tt)*)] |
574 | | $($tail:tt)* |
575 | | }, |
576 | | found_exhaustive_attr: $found_exhaustive:tt, |
577 | | vis: $vis:vis, |
578 | | name: $name:ident, |
579 | | body: { $($body:tt)* }, |
580 | | ) => { |
581 | | custom_struct! { |
582 | | @split_attrs, |
583 | | cfg_attrs: { $($cfg_attrs)* #[cfg($($cfg)*)] }, |
584 | | other_attrs: { $($other_attrs)* }, |
585 | | remaining_attrs: { $($tail)* }, |
586 | | found_exhaustive_attr: $found_exhaustive, |
587 | | vis: $vis, |
588 | | name: $name, |
589 | | body: { $($body)* }, |
590 | | } |
591 | | }; |
592 | | |
593 | | // `exhaustive` must be taken into account as many times as it appears, |
594 | | // though the effect is the same with a single annotation. |
595 | | ( |
596 | | @split_attrs, |
597 | | cfg_attrs: { $($cfg_attrs:tt)* }, |
598 | | other_attrs: { $($other_attrs:tt)* }, |
599 | | remaining_attrs: { |
600 | | #[exhaustive] |
601 | | $($tail:tt)* |
602 | | }, |
603 | | found_exhaustive_attr: $_:tt, |
604 | | vis: $vis:vis, |
605 | | name: $name:ident, |
606 | | body: { $($body:tt)* }, |
607 | | ) => { |
608 | | custom_struct! { |
609 | | @split_attrs, |
610 | | cfg_attrs: { $($cfg_attrs)* }, |
611 | | other_attrs: { $($other_attrs)* }, |
612 | | remaining_attrs: { $($tail)* }, |
613 | | found_exhaustive_attr: true, |
614 | | vis: $vis, |
615 | | name: $name, |
616 | | body: { $($body)* }, |
617 | | } |
618 | | }; |
619 | | |
620 | | // anything else belongs to the struct only |
621 | | ( |
622 | | @split_attrs, |
623 | | cfg_attrs: { $($cfg_attrs:tt)* }, |
624 | | other_attrs: { $($other_attrs:tt)* }, |
625 | | remaining_attrs: { |
626 | | #$other:tt |
627 | | $($tail:tt)* |
628 | | }, |
629 | | found_exhaustive_attr: $found_exhaustive:tt, |
630 | | vis: $vis:vis, |
631 | | name: $name:ident, |
632 | | body: { $($body:tt)* }, |
633 | | ) => { |
634 | | custom_struct! { |
635 | | @split_attrs, |
636 | | cfg_attrs: { $($cfg_attrs)* }, |
637 | | other_attrs: { $($other_attrs)* #$other }, |
638 | | remaining_attrs: { $($tail)* }, |
639 | | found_exhaustive_attr: $found_exhaustive, |
640 | | vis: $vis, |
641 | | name: $name, |
642 | | body: { $($body)* }, |
643 | | } |
644 | | }; |
645 | | |
646 | | // attributes are split, move on to the fields |
647 | | ( |
648 | | @split_attrs, |
649 | | cfg_attrs: { $($cfg_attrs:tt)* }, |
650 | | other_attrs: { $($other_attrs:tt)* }, |
651 | | remaining_attrs: { }, |
652 | | found_exhaustive_attr: $found_exhaustive:tt, |
653 | | vis: $vis:vis, |
654 | | name: $name:ident, |
655 | | body: { $($body:tt)* }, |
656 | | ) => { |
657 | | custom_struct! { |
658 | | @struct, |
659 | | cfg_attrs: { $($cfg_attrs)* }, |
660 | | other_attrs: { $($other_attrs)* }, |
661 | | found_exhaustive_attr: $found_exhaustive, |
662 | | vis: $vis, |
663 | | name: $name, |
664 | | processed_fields: { }, |
665 | | processed_field_defaults: { }, |
666 | | remaining_fields: { $($body)* }, |
667 | | } |
668 | | }; |
669 | | |
670 | | // field led by #[custom_default(...)] |
671 | | ( |
672 | | @struct, |
673 | | cfg_attrs: { $($cfg_attrs:tt)* }, |
674 | | other_attrs: { $($other_attrs:tt)* }, |
675 | | found_exhaustive_attr: $found_exhaustive:tt, |
676 | | vis: $vis:vis, |
677 | | name: $name:ident, |
678 | | processed_fields: { $($processed_fields:tt)* }, |
679 | | processed_field_defaults: { $($processed_field_defaults:tt)* }, |
680 | | remaining_fields: { |
681 | | #[custom_default($default:expr)] |
682 | | $(#[$fattr:meta])* |
683 | | $fvis:vis $fname:ident: $fty:ty, |
684 | | $($tail:tt)* |
685 | | }, |
686 | | ) => { |
687 | | custom_struct! { |
688 | | @struct, |
689 | | cfg_attrs: { $($cfg_attrs)* }, |
690 | | other_attrs: { $($other_attrs)* }, |
691 | | found_exhaustive_attr: $found_exhaustive, |
692 | | vis: $vis, |
693 | | name: $name, |
694 | | processed_fields: { $($processed_fields)* $(#[$fattr])* $fvis $fname: $fty, }, |
695 | | processed_field_defaults: { |
696 | | $($processed_field_defaults)* |
697 | | $(#[$fattr])* $fname: $default, |
698 | | }, |
699 | | remaining_fields: { $($tail)* }, |
700 | | } |
701 | | }; |
702 | | |
703 | | // plain field |
704 | | ( |
705 | | @struct, |
706 | | cfg_attrs: { $($cfg_attrs:tt)* }, |
707 | | other_attrs: { $($other_attrs:tt)* }, |
708 | | found_exhaustive_attr: $found_exhaustive:tt, |
709 | | vis: $vis:vis, |
710 | | name: $name:ident, |
711 | | processed_fields: { $($processed_fields:tt)* }, |
712 | | processed_field_defaults: { $($processed_field_defaults:tt)* }, |
713 | | remaining_fields: { |
714 | | $(#[$fattr:meta])* |
715 | | $fvis:vis $fname:ident: $fty:ty, |
716 | | $($tail:tt)* |
717 | | }, |
718 | | ) => { |
719 | | custom_struct! { |
720 | | @struct, |
721 | | cfg_attrs: { $($cfg_attrs)* }, |
722 | | other_attrs: { $($other_attrs)* }, |
723 | | found_exhaustive_attr: $found_exhaustive, |
724 | | vis: $vis, |
725 | | name: $name, |
726 | | processed_fields: { $($processed_fields)* $(#[$fattr])* $fvis $fname: $fty, }, |
727 | | processed_field_defaults: { |
728 | | $($processed_field_defaults)* |
729 | | $(#[$fattr])* $fname: ::core::default::Default::default(), |
730 | | }, |
731 | | remaining_fields: { $($tail)* }, |
732 | | } |
733 | | }; |
734 | | |
735 | | // done |
736 | | ( |
737 | | @struct, |
738 | | cfg_attrs: { $($cfg_attrs:tt)* }, |
739 | | other_attrs: { $($other_attrs:tt)* }, |
740 | | found_exhaustive_attr: $found_exhaustive:tt, |
741 | | vis: $vis:vis, |
742 | | name: $name:ident, |
743 | | processed_fields: { $($processed_fields:tt)* }, |
744 | | processed_field_defaults: { $($processed_field_defaults:tt)* }, |
745 | | remaining_fields: { }, |
746 | | ) => { |
747 | | emit_struct_definition! { |
748 | | found_exhaustive_attr: $found_exhaustive, |
749 | | body: { |
750 | | $($other_attrs)* |
751 | | $($cfg_attrs)* |
752 | | $vis $name { $($processed_fields)* } |
753 | | } |
754 | | } |
755 | | |
756 | | $($cfg_attrs)* |
757 | | // The impl names the type and its fields, which warns if either is |
758 | | // deprecated. |
759 | | #[allow(deprecated)] |
760 | | impl ::core::default::Default for $name { |
761 | | // Field attributes (`#[cfg]`, doc comments) get forwarded to the |
762 | | // initializer too. Docs are harmless there but trip the lint, so |
763 | | // silence it. |
764 | | #[allow(unused_doc_comments)] |
765 | 0 | fn default() -> Self { |
766 | 0 | emit_struct_default_body! { |
767 | | found_exhaustive_attr: $found_exhaustive, |
768 | | body: { $($processed_field_defaults)* } |
769 | | } |
770 | 0 | } Unexecuted instantiation: <libc::new::linux_uapi::linux::can::can_frame as core::default::Default>::default Unexecuted instantiation: <libc::new::glibc::sysdeps::unix::linux::bits::statvfs::statvfs as core::default::Default>::default Unexecuted instantiation: <libc::unix::protoent as core::default::Default>::default Unexecuted instantiation: <libc::unix::in6_addr as core::default::Default>::default Unexecuted instantiation: <libc::new::linux_uapi::linux::can::canfd_frame as core::default::Default>::default Unexecuted instantiation: <libc::new::glibc::sysdeps::unix::linux::bits::statvfs::statvfs64 as core::default::Default>::default Unexecuted instantiation: <libc::unix::group as core::default::Default>::default Unexecuted instantiation: <libc::new::linux_uapi::linux::can::canxl_frame as core::default::Default>::default Unexecuted instantiation: <libc::unix::utimbuf as core::default::Default>::default Unexecuted instantiation: <libc::unix::winsize as core::default::Default>::default Unexecuted instantiation: <libc::unix::linger as core::default::Default>::default Unexecuted instantiation: <libc::unix::sigval as core::default::Default>::default Unexecuted instantiation: <libc::unix::itimerval as core::default::Default>::default Unexecuted instantiation: <libc::unix::tms as core::default::Default>::default Unexecuted instantiation: <libc::unix::servent as core::default::Default>::default Unexecuted instantiation: <libc::new::linux_uapi::linux::can::sockaddr_can as core::default::Default>::default Unexecuted instantiation: <libc::unix::timeval as core::default::Default>::default Unexecuted instantiation: <libc::unix::rlimit as core::default::Default>::default Unexecuted instantiation: <libc::new::linux_uapi::linux::can::__c_anonymous_sockaddr_can_tp as core::default::Default>::default Unexecuted instantiation: <libc::unix::rusage as core::default::Default>::default Unexecuted instantiation: <libc::new::linux_uapi::linux::can::__c_anonymous_sockaddr_can_j1939 as core::default::Default>::default Unexecuted instantiation: <libc::unix::ipv6_mreq as core::default::Default>::default Unexecuted instantiation: <libc::new::linux_uapi::linux::can::can_filter as core::default::Default>::default Unexecuted instantiation: <libc::unix::hostent as core::default::Default>::default Unexecuted instantiation: <libc::unix::iovec as core::default::Default>::default Unexecuted instantiation: <libc::unix::pollfd as core::default::Default>::default |
771 | | } |
772 | | }; |
773 | | } |
774 | | |
775 | | /// Expands the definition of the record defined at [`custom_struct`], with either one of an |
776 | | /// additional private field or with its verbatim fields. |
777 | | macro_rules! emit_struct_definition { |
778 | | ( |
779 | | found_exhaustive_attr: false, |
780 | | body: { $(#[$attr:meta])* $vis:vis $name:ident { $($field:tt)* } } |
781 | | ) => { |
782 | | #[allow(clippy::manual_non_exhaustive)] |
783 | | $(#[$attr])* |
784 | | $vis struct $name { $($field)* __non_exhaustive: () } |
785 | | }; |
786 | | |
787 | | ( |
788 | | found_exhaustive_attr: true, |
789 | | body: { $(#[$attr:meta])* $vis:vis $name:ident { $($field:tt)* } } |
790 | | ) => { |
791 | | $(#[$attr])* |
792 | | $vis struct $name { $($field)* } |
793 | | }; |
794 | | } |
795 | | |
796 | | /// Expands the `Default` implementation of the record defined at [`custom_struct`], with either one |
797 | | /// of an additional private field initialized to the unit value, or the record's fields verbatim. |
798 | | macro_rules! emit_struct_default_body { |
799 | | ( |
800 | | found_exhaustive_attr: false, |
801 | | body: { $($field_default:tt)* } |
802 | | ) => { |
803 | | Self { $($field_default)* __non_exhaustive: () } |
804 | | }; |
805 | | |
806 | | ( |
807 | | found_exhaustive_attr: true, |
808 | | body: { $($field_default:tt)* } |
809 | | ) => { |
810 | | Self { $($field_default)* } |
811 | | }; |
812 | | } |
813 | | |
814 | | /// Create an uninhabited type that can't be constructed. It implements `Debug`, `Clone`, and |
815 | | /// `Copy`, but these aren't meaningful for extern types so they should eventually be removed. |
816 | | /// |
817 | | /// Really what we want here is something that also can't be named without indirection (in ADTs or |
818 | | /// function signatures), but this doesn't exist. |
819 | | macro_rules! extern_ty { |
820 | | ($( |
821 | | $(#[$attr:meta])* |
822 | | $vis:vis type $i:ident; |
823 | | )*) => ($( |
824 | | $(#[$attr])* |
825 | | /// This is an extern type ("opaque" or "incomplete" type in C). |
826 | | /// |
827 | | /// <div class="warning"> |
828 | | /// This type's current representation allows inspecting some properties, such as via |
829 | | /// <code>size_of</code>, and it is technically possible to construct the type within |
830 | | /// <code>MaybeUninit</code>, However, this <strong>MUST NOT</strong> be relied upon |
831 | | /// because a future version of <code>libc</code> may switch to a proper |
832 | | /// <a href="https://rust-lang.github.io/rfcs/1861-extern-types.html">extern type</a> |
833 | | /// representation when available. |
834 | | /// </div> |
835 | | // ^ unfortunately warning blocks currently don't render markdown so we need to |
836 | | // use raw HTML. |
837 | | // |
838 | | // Representation based on the Nomicon: |
839 | | // <https://doc.rust-lang.org/nomicon/ffi.html#representing-opaque-structs>. |
840 | | // |
841 | | // FIXME(1.0): These traits are unreachable and should be removed. |
842 | | #[::core::prelude::v1::derive( |
843 | | ::core::clone::Clone, |
844 | | ::core::marker::Copy, |
845 | | ::core::fmt::Debug, |
846 | | )] |
847 | | #[repr(C)] |
848 | | $vis struct $i { |
849 | | _data: (), |
850 | | _marker: ::core::marker::PhantomData<(*mut u8, ::core::marker::PhantomPinned)>, |
851 | | } |
852 | | )*); |
853 | | } |
854 | | |
855 | | /// Implement `Clone` and `Copy` for an enum, as well as `Debug`, `Eq`, `Hash`, and |
856 | | /// `PartialEq` if the `extra_traits` feature is enabled. |
857 | | // FIXME(#4419): Replace all uses of `e!` with `c_enum!` |
858 | | macro_rules! e { |
859 | | ($( |
860 | | $(#[$attr:meta])* |
861 | | pub enum $i:ident { $($field:tt)* } |
862 | | )*) => ($( |
863 | | #[cfg_attr( |
864 | | feature = "extra_traits", |
865 | | ::core::prelude::v1::derive(Eq, Hash, PartialEq) |
866 | | )] |
867 | | #[::core::prelude::v1::derive( |
868 | | ::core::clone::Clone, |
869 | | ::core::marker::Copy, |
870 | | ::core::fmt::Debug, |
871 | | )] |
872 | | $(#[$attr])* |
873 | | pub enum $i { $($field)* } |
874 | | )*); |
875 | | } |
876 | | |
877 | | /// Represent a C enum as Rust constants and a type. |
878 | | /// |
879 | | /// C enums can't soundly be mapped to Rust enums since C enums are allowed to have duplicates or |
880 | | /// unlisted values, but this is UB in Rust. This enum doesn't implement any traits, its main |
881 | | /// purpose is to calculate the correct enum values. |
882 | | /// |
883 | | /// Use the magic name `#anon` if the C enum doesn't create a type. |
884 | | /// |
885 | | /// See <https://github.com/rust-lang/libc/issues/4419> for more. |
886 | | macro_rules! c_enum { |
887 | | // Matcher for multiple enums |
888 | | ($( |
889 | | $(#[repr($repr:ty)])? |
890 | | $vis:vis enum $($ty_name:ident)? $(#$anon:ident)? { |
891 | | $( |
892 | | $(#[$meta:meta])* |
893 | | $field_vis:vis $variant:ident $(= $value:expr)?, |
894 | | )+ |
895 | | } |
896 | | )+) => { |
897 | | $(c_enum!(@single; |
898 | | $(#[repr($repr)])? |
899 | | $vis enum $($ty_name)? $(#$anon)? { |
900 | | $( |
901 | | $(#[$meta])* |
902 | | $field_vis $variant $(= $value)?, |
903 | | )+ |
904 | | } |
905 | | );)+ |
906 | | }; |
907 | | |
908 | | // Matcher for a single enum |
909 | | (@single; |
910 | | $(#[repr($repr:ty)])? |
911 | | $vis:vis enum $ty_name:ident { |
912 | | $( |
913 | | $(#[$meta:meta])* |
914 | | $field_vis:vis $variant:ident $(= $value:expr)?, |
915 | | )+ |
916 | | } |
917 | | ) => { |
918 | | $vis type $ty_name = c_enum!(@ty $($repr)?); |
919 | | c_enum! { |
920 | | @variant; |
921 | | ty: $ty_name; |
922 | | default: 0; |
923 | | variants: [$( |
924 | | $(#[$meta])* |
925 | | $field_vis $variant $(= $value)?, |
926 | | )+] |
927 | | } |
928 | | }; |
929 | | |
930 | | // Matcher for a single anonymous enum |
931 | | (@single; |
932 | | $(#[repr($repr:ty)])? |
933 | | $vis:vis enum #anon { |
934 | | $( |
935 | | $(#[$meta:meta])* |
936 | | $field_vis:vis $variant:ident $(= $value:expr)?, |
937 | | )+ |
938 | | } |
939 | | ) => { |
940 | | c_enum! { |
941 | | @variant; |
942 | | ty: c_enum!(@ty $($repr)?); |
943 | | default: 0; |
944 | | variants: [$( |
945 | | $(#[$meta])* |
946 | | $field_vis $variant $(= $value)?, |
947 | | )+] |
948 | | } |
949 | | }; |
950 | | |
951 | | // Matcher for variants: eats a single variant then recurses with the rest |
952 | | (@variant; |
953 | | ty: $_ty_name:ty; |
954 | | default: $_idx:expr; |
955 | | variants: [] |
956 | | ) => { /* end of the chain */ }; |
957 | | ( |
958 | | @variant; |
959 | | ty: $ty_name:ty; |
960 | | default: $default_val:expr; |
961 | | variants: [ |
962 | | $(#[$meta:meta])* |
963 | | $field_vis:vis $variant:ident $(= $value:expr)?, |
964 | | $($tail:tt)* |
965 | | ] |
966 | | ) => { |
967 | | $(#[$meta])* |
968 | | #[allow(deprecated)] |
969 | | $field_vis const $variant: $ty_name = { |
970 | | #[allow(unused_variables)] |
971 | | let r = $default_val; |
972 | | $(let r = $value;)? |
973 | | r |
974 | | }; |
975 | | |
976 | | // The next value is always one more than the previous value, unless |
977 | | // set explicitly. |
978 | | c_enum! { |
979 | | @variant; |
980 | | ty: $ty_name; |
981 | | default: $variant + 1; |
982 | | variants: [$($tail)*] |
983 | | } |
984 | | }; |
985 | | |
986 | | // Use a specific type if provided, otherwise default to `CEnumRepr` |
987 | | (@ty $repr:ty) => { $repr }; |
988 | | (@ty) => { $crate::prelude::CEnumRepr }; |
989 | | } |
990 | | |
991 | | /// Define a function that can be either `safe` or `unsafe` and optionally `const`. This always |
992 | | /// marks the function inline and adds `extern "C"`. |
993 | | macro_rules! f { |
994 | | ($( |
995 | | $(#[$attr:meta])* |
996 | | pub $(const $($const_dummy:literal)?)? |
997 | | $(unsafe $($unsafe_dummy:literal)?)? $(safe $($safe_dummy:literal)?)? |
998 | | fn $i:ident ($($arg:ident: $argty:ty),* $(,)?) -> $ret:ty |
999 | | $body:block |
1000 | | )+) => {$( |
1001 | | f! { |
1002 | | @single |
1003 | | $(#[$attr])* |
1004 | | pub $(const $($const_dummy)?)? |
1005 | | $(unsafe $($unsafe_dummy)?)? $(safe $($safe_dummy)?)? |
1006 | | fn $i ($($arg: $argty),*) -> $ret |
1007 | | $body |
1008 | | } |
1009 | | )+}; |
1010 | | |
1011 | | (@single |
1012 | | $(#[$attr:meta])* |
1013 | | pub $(const $($const_dummy:literal)?)? unsafe |
1014 | | fn $i:ident ($($arg:ident: $argty:ty),* $(,)?) -> $ret:ty |
1015 | | $body:block |
1016 | | ) => { |
1017 | | #[inline] |
1018 | | $(#[$attr])* |
1019 | | pub $(const $($const_dummy)?)? unsafe extern "C" |
1020 | | fn $i ($($arg: $argty),*) -> $ret |
1021 | | $body |
1022 | | }; |
1023 | | |
1024 | | (@single |
1025 | | $(#[$attr:meta])* |
1026 | | pub $(const $($const_dummy:literal)?)? safe |
1027 | | fn $i:ident ($($arg:ident: $argty:ty),* $(,)?) -> $ret:ty |
1028 | | $body:block |
1029 | | ) => { |
1030 | | #[inline] |
1031 | | $(#[$attr])* |
1032 | | pub $(const $($const_dummy)?)? extern "C" |
1033 | | fn $i ($($arg: $argty),*) -> $ret |
1034 | | $body |
1035 | | }; |
1036 | | |
1037 | | (@single |
1038 | | pub $(const $($const_dummy:literal)?)? |
1039 | | fn $i:ident ($($arg:ident: $argty:ty),* $(,)?) -> $ret:ty |
1040 | | $body:block |
1041 | | ) => { |
1042 | | compile_error!("either `safe` or `unsafe` must be specified"); |
1043 | | }; |
1044 | | } |
1045 | | |
1046 | | // This macro is used to deprecate items that should be accessed via the mach2 crate |
1047 | | macro_rules! deprecated_mach { |
1048 | | (pub const $id:ident: $ty:ty = $expr:expr;) => { |
1049 | | #[deprecated( |
1050 | | since = "0.2.55", |
1051 | | note = "Use the `mach2` crate instead", |
1052 | | )] |
1053 | | #[allow(deprecated)] |
1054 | | pub const $id: $ty = $expr; |
1055 | | }; |
1056 | | ($(pub const $id:ident: $ty:ty = $expr:expr;)*) => { |
1057 | | $( |
1058 | | deprecated_mach!( |
1059 | | pub const $id: $ty = $expr; |
1060 | | ); |
1061 | | )* |
1062 | | }; |
1063 | | (pub type $id:ident = $ty:ty;) => { |
1064 | | #[deprecated( |
1065 | | since = "0.2.55", |
1066 | | note = "Use the `mach2` crate instead", |
1067 | | )] |
1068 | | #[allow(deprecated)] |
1069 | | pub type $id = $ty; |
1070 | | }; |
1071 | | ($(pub type $id:ident = $ty:ty;)*) => { |
1072 | | $( |
1073 | | deprecated_mach!( |
1074 | | pub type $id = $ty; |
1075 | | ); |
1076 | | )* |
1077 | | } |
1078 | | } |
1079 | | |
1080 | | /// Polyfill for std's `offset_of`. |
1081 | | // FIXME(msrv): stabilized in std in 1.77 |
1082 | | macro_rules! offset_of { |
1083 | | ($Ty:path, $field:ident) => {{ |
1084 | | // Taken from bytemuck, avoids accidentally calling on deref |
1085 | | #[allow(clippy::unneeded_wildcard_pattern)] |
1086 | | let $Ty { $field: _, .. }; |
1087 | | let data = core::mem::MaybeUninit::<$Ty>::uninit(); |
1088 | | let ptr = data.as_ptr(); |
1089 | | // nested unsafe, see f! |
1090 | | #[allow(unused_unsafe)] |
1091 | | // SAFETY: computed address is inbounds since we have a stack alloc for |
1092 | | // T |
1093 | | let fptr = unsafe { core::ptr::addr_of!((*ptr).$field) }; |
1094 | | let off = (fptr as usize).checked_sub(ptr as usize).unwrap(); |
1095 | | core::assert!(off <= core::mem::size_of::<$Ty>()); |
1096 | | off |
1097 | | }}; |
1098 | | } |
1099 | | |
1100 | | #[cfg(test)] |
1101 | | mod tests { |
1102 | | use core::any::TypeId; |
1103 | | use core::prelude::v1::*; |
1104 | | |
1105 | | use crate::types::CEnumRepr; |
1106 | | |
1107 | | #[test] |
1108 | | fn c_enum_basic() { |
1109 | | // By default, variants get sequential values. |
1110 | | c_enum! { |
1111 | | pub enum e { |
1112 | | VAR0, |
1113 | | VAR1, |
1114 | | VAR2, |
1115 | | } |
1116 | | |
1117 | | // Also check enums that don't create a type. |
1118 | | pub enum #anon { |
1119 | | ANON0, |
1120 | | ANON1, |
1121 | | ANON2, |
1122 | | } |
1123 | | |
1124 | | // No visibility required. |
1125 | | enum #anon { |
1126 | | ANON3, |
1127 | | ANON4, |
1128 | | ANON5, |
1129 | | } |
1130 | | } |
1131 | | |
1132 | | assert_eq!(TypeId::of::<e>(), TypeId::of::<CEnumRepr>()); |
1133 | | assert_eq!(VAR0, 0 as CEnumRepr); |
1134 | | assert_eq!(VAR1, 1 as CEnumRepr); |
1135 | | assert_eq!(VAR2, 2 as CEnumRepr); |
1136 | | |
1137 | | assert_eq!(type_id_of_val(&ANON0), TypeId::of::<CEnumRepr>()); |
1138 | | assert_eq!(ANON0, 0 as CEnumRepr); |
1139 | | assert_eq!(ANON1, 1 as CEnumRepr); |
1140 | | assert_eq!(ANON2, 2 as CEnumRepr); |
1141 | | |
1142 | | assert_eq!(type_id_of_val(&ANON3), TypeId::of::<CEnumRepr>()); |
1143 | | assert_eq!(ANON3, 0 as CEnumRepr); |
1144 | | assert_eq!(ANON4, 1 as CEnumRepr); |
1145 | | assert_eq!(ANON5, 2 as CEnumRepr); |
1146 | | } |
1147 | | |
1148 | | #[test] |
1149 | | fn c_enum_repr() { |
1150 | | // Check specifying the integer representation |
1151 | | c_enum! { |
1152 | | #[repr(u16)] |
1153 | | pub enum e { |
1154 | | VAR0, |
1155 | | } |
1156 | | |
1157 | | #[repr(u16)] |
1158 | | pub enum #anon { |
1159 | | ANON0, |
1160 | | } |
1161 | | } |
1162 | | |
1163 | | assert_eq!(TypeId::of::<e>(), TypeId::of::<u16>()); |
1164 | | assert_eq!(VAR0, 0_u16); |
1165 | | |
1166 | | assert_eq!(type_id_of_val(&ANON0), TypeId::of::<u16>()); |
1167 | | assert_eq!(ANON0, 0_u16); |
1168 | | } |
1169 | | |
1170 | | #[test] |
1171 | | fn c_enum_set_value() { |
1172 | | // Setting an explicit value resets the count. |
1173 | | c_enum! { |
1174 | | pub enum e { |
1175 | | VAR2 = 2, |
1176 | | VAR3, |
1177 | | VAR4, |
1178 | | } |
1179 | | } |
1180 | | |
1181 | | assert_eq!(VAR2, 2 as CEnumRepr); |
1182 | | assert_eq!(VAR3, 3 as CEnumRepr); |
1183 | | assert_eq!(VAR4, 4 as CEnumRepr); |
1184 | | } |
1185 | | |
1186 | | #[test] |
1187 | | fn c_enum_multiple_set_value() { |
1188 | | // C enums always take one more than the previous value, unless set to a |
1189 | | // specific value. Duplicates are allowed. |
1190 | | c_enum! { |
1191 | | pub enum e { |
1192 | | VAR0, |
1193 | | VAR2_0 = 2, |
1194 | | VAR3_0, |
1195 | | VAR4_0, |
1196 | | VAR2_1 = 2, |
1197 | | VAR3_1, |
1198 | | VAR4_1, |
1199 | | } |
1200 | | } |
1201 | | |
1202 | | assert_eq!(VAR0, 0 as CEnumRepr); |
1203 | | assert_eq!(VAR2_0, 2 as CEnumRepr); |
1204 | | assert_eq!(VAR3_0, 3 as CEnumRepr); |
1205 | | assert_eq!(VAR4_0, 4 as CEnumRepr); |
1206 | | assert_eq!(VAR2_1, 2 as CEnumRepr); |
1207 | | assert_eq!(VAR3_1, 3 as CEnumRepr); |
1208 | | assert_eq!(VAR4_1, 4 as CEnumRepr); |
1209 | | } |
1210 | | |
1211 | | #[test] |
1212 | | fn c_enum_vis() { |
1213 | | mod priv1 { |
1214 | | c_enum! { |
1215 | | #[repr(u8)] |
1216 | | pub enum e1 { |
1217 | | PRIV_ON_1 = 10, |
1218 | | // Variant should still be usable within its visibility |
1219 | | pub PUB1 = PRIV_ON_1 * 2, |
1220 | | } |
1221 | | } |
1222 | | } |
1223 | | mod priv2 { |
1224 | | c_enum! { |
1225 | | #[repr(u16)] |
1226 | | pub enum e2 { |
1227 | | pub PRIV_ON_1 = 42, |
1228 | | pub PUB2 = PRIV_ON_1 * 2, |
1229 | | } |
1230 | | } |
1231 | | } |
1232 | | |
1233 | | use priv1::*; |
1234 | | use priv2::*; |
1235 | | |
1236 | | assert_eq!(TypeId::of::<e1>(), TypeId::of::<u8>()); |
1237 | | assert_eq!(TypeId::of::<e2>(), TypeId::of::<u16>()); |
1238 | | assert_eq!(PUB1, 10u8 * 2); |
1239 | | assert_eq!(PUB2, 42u16 * 2); |
1240 | | // Verify that the default is private. If `PRIV_ON_1` was actually |
1241 | | // public in `priv1`, this would be an ambiguous import and/or type |
1242 | | // mismatch error. |
1243 | | assert_eq!(PRIV_ON_1, 42u16); |
1244 | | } |
1245 | | |
1246 | | #[test] |
1247 | | fn c_enum_attrs() { |
1248 | | // Note this can't work with `#[cfg]` currently because our expansion uses `previous + 1` |
1249 | | c_enum! { |
1250 | | pub enum e { |
1251 | | VAR0, |
1252 | | WITH_CFG = if cfg!(target_arch = "x86_64") { 86 } else { 1234 }, |
1253 | | #[deprecated] |
1254 | | DEPRECATED, |
1255 | | NOT_DEPRECATED, |
1256 | | } |
1257 | | } |
1258 | | |
1259 | | if cfg!(target_arch = "x86_64") { |
1260 | | assert_eq!(WITH_CFG, 86); |
1261 | | } else { |
1262 | | assert_eq!(WITH_CFG, 1234); |
1263 | | } |
1264 | | |
1265 | | #[expect(deprecated)] |
1266 | | let _ = DEPRECATED; |
1267 | | #[deny(deprecated)] |
1268 | | let _ = NOT_DEPRECATED; |
1269 | | } |
1270 | | |
1271 | | #[test] |
1272 | | #[deny(unused_unsafe)] |
1273 | | fn f_safety() { |
1274 | | // Enusure the created functions are safe / unsafe / const as expected |
1275 | | f! { |
1276 | | pub unsafe fn unsafe_foo() -> u32 { 100 } |
1277 | | pub const unsafe fn const_unsafe_foo() -> u32 { 101 } |
1278 | | pub safe fn safe_foo() -> u32 { 200 } |
1279 | | pub const safe fn const_safe_foo() -> u32 { 201 } |
1280 | | } |
1281 | | |
1282 | | assert_eq!(unsafe { unsafe_foo() }, 100u32); |
1283 | | assert_eq!(const { unsafe { const_unsafe_foo() } }, 101u32); |
1284 | | assert_eq!(safe_foo(), 200u32); |
1285 | | assert_eq!(const { const_safe_foo() }, 201u32); |
1286 | | |
1287 | | // Check the ABI |
1288 | | let _: unsafe extern "C" fn() -> u32 = unsafe_foo; |
1289 | | let _: unsafe extern "C" fn() -> u32 = const_unsafe_foo; |
1290 | | let _: extern "C" fn() -> u32 = safe_foo; |
1291 | | let _: extern "C" fn() -> u32 = const_safe_foo; |
1292 | | } |
1293 | | |
1294 | | fn type_id_of_val<T: 'static>(_: &T) -> TypeId { |
1295 | | TypeId::of::<T>() |
1296 | | } |
1297 | | |
1298 | | #[test] |
1299 | | fn test_offset_of() { |
1300 | | #[repr(C)] |
1301 | | struct Off1 { |
1302 | | a: u8, |
1303 | | b: u32, |
1304 | | c: Off2, |
1305 | | d: u64, |
1306 | | } |
1307 | | |
1308 | | #[repr(C)] |
1309 | | #[repr(align(128))] |
1310 | | struct Off2 {} |
1311 | | |
1312 | | assert_eq!(core::mem::offset_of!(Off1, a), offset_of!(Off1, a)); |
1313 | | assert_eq!(core::mem::offset_of!(Off1, b), offset_of!(Off1, b)); |
1314 | | assert_eq!(core::mem::offset_of!(Off1, c), offset_of!(Off1, c)); |
1315 | | assert_eq!(core::mem::offset_of!(Off1, d), offset_of!(Off1, d)); |
1316 | | } |
1317 | | |
1318 | | #[test] |
1319 | | fn s2_is_non_exhaustive() { |
1320 | | // Without `#[exhaustive]`, the record should have an additional field |
1321 | | // added at the end. If this test compiles, it has it. |
1322 | | s2! { |
1323 | | struct Something { |
1324 | | a: u32, |
1325 | | } |
1326 | | } |
1327 | | |
1328 | | let s = Something::default(); |
1329 | | assert_eq!(s.__non_exhaustive, ()); |
1330 | | } |
1331 | | |
1332 | | #[test] |
1333 | | fn s2_uses_exhaustive() { |
1334 | | // With `#[exhaustive]`, the record should be regurgitated as-is. If |
1335 | | // this test compiles, then it works. |
1336 | | s2! { |
1337 | | #[exhaustive] |
1338 | | struct Something { |
1339 | | a: u32, |
1340 | | } |
1341 | | } |
1342 | | |
1343 | | #[allow(unused)] |
1344 | | let s = Something { |
1345 | | a: Default::default(), |
1346 | | }; |
1347 | | } |
1348 | | |
1349 | | #[test] |
1350 | | fn s2_uses_mixed_exhaustive() { |
1351 | | // `#[exhaustive]` should work when sandwiched between attributes. If |
1352 | | // the test compiles, then it works. |
1353 | | s2! { |
1354 | | #[repr(align(8))] |
1355 | | #[exhaustive] |
1356 | | #[repr(align(2))] |
1357 | | struct Something { |
1358 | | a: u32, |
1359 | | } |
1360 | | } |
1361 | | |
1362 | | #[allow(unused)] |
1363 | | let s = Something { |
1364 | | a: Default::default(), |
1365 | | }; |
1366 | | } |
1367 | | |
1368 | | #[test] |
1369 | | fn s2_uses_custom_default() { |
1370 | | // A non-default value proves `custom_default` is used rather than a |
1371 | | // derived default. |
1372 | | s2! { |
1373 | | struct CustomDefault { |
1374 | | a: u32, |
1375 | | #[custom_default([1; 64])] |
1376 | | buf: [u8; 64], |
1377 | | } |
1378 | | } |
1379 | | |
1380 | | let s = CustomDefault::default(); |
1381 | | assert_eq!(s.a, 0); |
1382 | | assert_eq!(s.buf, [1u8; 64]); |
1383 | | } |
1384 | | |
1385 | | #[test] |
1386 | | fn s2_keeps_field_attrs() { |
1387 | | // If `custom_default` stripping ate the other field attributes, the two |
1388 | | // `a` fields would collide. |
1389 | | s2! { |
1390 | | struct FieldAttrs { |
1391 | | #[cfg(target_arch = "x86_64")] |
1392 | | a: u8, |
1393 | | #[cfg(not(target_arch = "x86_64"))] |
1394 | | a: u64, |
1395 | | } |
1396 | | } |
1397 | | |
1398 | | let s = FieldAttrs::default(); |
1399 | | #[cfg(target_arch = "x86_64")] |
1400 | | assert_eq!(s.a, 0u8); |
1401 | | #[cfg(not(target_arch = "x86_64"))] |
1402 | | assert_eq!(s.a, 0u64); |
1403 | | } |
1404 | | |
1405 | | #[test] |
1406 | | fn s2_single_cfg_field() { |
1407 | | // This field only exists on x86_64, so its default init needs the same |
1408 | | // `cfg` or `Default` won't build on other arches. |
1409 | | s2! { |
1410 | | struct SingleCfg { |
1411 | | common: u32, |
1412 | | #[cfg(target_arch = "x86_64")] |
1413 | | x86_only: u64, |
1414 | | } |
1415 | | } |
1416 | | |
1417 | | let s = SingleCfg::default(); |
1418 | | assert_eq!(s.common, 0); |
1419 | | #[cfg(target_arch = "x86_64")] |
1420 | | assert_eq!(s.x86_only, 0); |
1421 | | } |
1422 | | |
1423 | | #[test] |
1424 | | fn s_no_extra_traits2_zeroes_union() { |
1425 | | // A union field's default is supplied by |
1426 | | // `custom_default(unsafe { mem::zeroed })`. |
1427 | | s_no_extra_traits2! { |
1428 | | union U { |
1429 | | a: u32, |
1430 | | b: f32, |
1431 | | } |
1432 | | |
1433 | | struct HasUnion { |
1434 | | x: u16, |
1435 | | #[custom_default(unsafe { ::core::mem::zeroed::<U>() })] |
1436 | | u: U, |
1437 | | } |
1438 | | } |
1439 | | |
1440 | | let s = HasUnion::default(); |
1441 | | assert_eq!(s.x, 0); |
1442 | | assert_eq!(unsafe { s.u.a }, 0); |
1443 | | } |
1444 | | |
1445 | | #[test] |
1446 | | fn s2_keeps_struct_cfg() { |
1447 | | // The opposite of the configured-out types in `macro_checks`. With the |
1448 | | // `cfg` true the type and its `Default` both exist, and the other |
1449 | | // attributes still apply. |
1450 | | s2! { |
1451 | | #[cfg(true)] |
1452 | | #[repr(align(8))] |
1453 | | /// a doc comment |
1454 | | struct EnabledCfg { |
1455 | | a: u32, |
1456 | | #[cfg(target_arch = "x86_64")] |
1457 | | x86_only: u8, |
1458 | | #[custom_default([1; 40])] |
1459 | | buf: [u8; 40], |
1460 | | } |
1461 | | } |
1462 | | |
1463 | | let s = EnabledCfg::default(); |
1464 | | assert_eq!(s.a, 0); |
1465 | | assert_eq!(s.buf, [1u8; 40]); |
1466 | | assert_eq!(align_of::<EnabledCfg>(), 8); |
1467 | | #[cfg(target_arch = "x86_64")] |
1468 | | assert_eq!(s.x86_only, 0); |
1469 | | } |
1470 | | |
1471 | | #[test] |
1472 | | fn s2_union_default() { |
1473 | | s_no_extra_traits2! { |
1474 | | #[unsafe(union_default_via_zeroed)] |
1475 | | union Foo { |
1476 | | a: u32, |
1477 | | b: u64 |
1478 | | } |
1479 | | |
1480 | | #[expect(unused)] |
1481 | | union Bar { |
1482 | | a: u32, |
1483 | | b: u64 |
1484 | | } |
1485 | | } |
1486 | | |
1487 | | let f: Foo = Foo::default(); |
1488 | | assert_eq!(unsafe { f.b }, 0); |
1489 | | |
1490 | | // Ensure it isn't always implemented, otherwise we would get a conflict. |
1491 | | impl Default for Bar { |
1492 | | fn default() -> Self { |
1493 | | unimplemented!() |
1494 | | } |
1495 | | } |
1496 | | } |
1497 | | } |
1498 | | |
1499 | | #[cfg(test)] |
1500 | | #[allow(unused)] |
1501 | | mod macro_checks { |
1502 | | use core::prelude::v1::*; |
1503 | | |
1504 | | s! { |
1505 | | pub struct S1 { |
1506 | | pub a: u32, |
1507 | | b: u32, |
1508 | | } |
1509 | | |
1510 | | struct S1Priv { |
1511 | | pub a: u32, |
1512 | | b: u32, |
1513 | | } |
1514 | | } |
1515 | | |
1516 | | s_no_extra_traits! { |
1517 | | pub struct S2 { |
1518 | | pub a: u32, |
1519 | | b: u32, |
1520 | | } |
1521 | | |
1522 | | struct S2Priv { |
1523 | | pub a: u32, |
1524 | | b: u32, |
1525 | | } |
1526 | | |
1527 | | pub union U2 { |
1528 | | pub a: u32, |
1529 | | b: f32, |
1530 | | } |
1531 | | |
1532 | | union U2Priv { |
1533 | | pub a: u32, |
1534 | | b: f32, |
1535 | | } |
1536 | | } |
1537 | | |
1538 | | extern_ty! { |
1539 | | type Foo; |
1540 | | pub type Bar; |
1541 | | } |
1542 | | |
1543 | | s2! { |
1544 | | pub struct S3 { |
1545 | | pub a: u32, |
1546 | | #[custom_default([1; 64])] |
1547 | | pub buf: [u8; 64], |
1548 | | } |
1549 | | |
1550 | | struct S3Priv { |
1551 | | pub a: u32, |
1552 | | b: u32, |
1553 | | } |
1554 | | } |
1555 | | |
1556 | | s_no_extra_traits2! { |
1557 | | pub union U3 { |
1558 | | pub a: u32, |
1559 | | b: f32, |
1560 | | } |
1561 | | |
1562 | | pub struct S4 { |
1563 | | pub a: u32, |
1564 | | #[custom_default(unsafe { ::core::mem::zeroed::<U3>() })] |
1565 | | pub u: U3, |
1566 | | } |
1567 | | } |
1568 | | |
1569 | | fn assert_impls_default<T: Default>() {} |
1570 | | |
1571 | | fn check_default() { |
1572 | | assert_impls_default::<S3>(); |
1573 | | assert_impls_default::<S4>(); |
1574 | | } |
1575 | | |
1576 | | // Types configured out entirely, checking that the generated impls carry |
1577 | | // the same `cfg` as the type. Without it they fail to compile with "cannot |
1578 | | // find type". |
1579 | | s2! { |
1580 | | #[cfg(false)] |
1581 | | pub struct S5 { |
1582 | | pub a: u32, |
1583 | | #[custom_default([1; 64])] |
1584 | | pub buf: [u8; 64], |
1585 | | } |
1586 | | } |
1587 | | |
1588 | | s_no_extra_traits! { |
1589 | | #[cfg(false)] |
1590 | | pub union U4 { |
1591 | | pub a: u32, |
1592 | | b: f32, |
1593 | | } |
1594 | | } |
1595 | | |
1596 | | s_no_extra_traits2! { |
1597 | | #[cfg(false)] |
1598 | | pub union U5 { |
1599 | | pub a: u32, |
1600 | | b: f32, |
1601 | | } |
1602 | | |
1603 | | #[cfg(false)] |
1604 | | pub struct S6 { |
1605 | | pub a: u32, |
1606 | | } |
1607 | | } |
1608 | | |
1609 | | // The generated impls name the type and its fields, so they need to allow |
1610 | | // deprecation. `deny` turns the warning into an error if that ever stops |
1611 | | // being the case. |
1612 | | mod deprecated_checks { |
1613 | | #![deny(deprecated)] |
1614 | | |
1615 | | s2! { |
1616 | | #[deprecated(since = "0.0.0", note = "check that generated impls don't warn")] |
1617 | | pub struct S7 { |
1618 | | pub a: u32, |
1619 | | } |
1620 | | } |
1621 | | |
1622 | | s_no_extra_traits! { |
1623 | | #[deprecated(since = "0.0.0", note = "check that generated impls don't warn")] |
1624 | | pub union U6 { |
1625 | | pub a: u32, |
1626 | | b: f32, |
1627 | | } |
1628 | | } |
1629 | | |
1630 | | s_no_extra_traits2! { |
1631 | | #[deprecated(since = "0.0.0", note = "check that generated impls don't warn")] |
1632 | | pub union U7 { |
1633 | | pub a: u32, |
1634 | | b: f32, |
1635 | | } |
1636 | | } |
1637 | | } |
1638 | | } |