libc/
macros.rs

1/// A macro for defining #[cfg] if-else statements.
2///
3/// This is similar to the `if/elif` C preprocessor macro by allowing definition
4/// of a cascade of `#[cfg]` cases, emitting the implementation which matches
5/// first.
6///
7/// This allows you to conveniently provide a long list #[cfg]'d blocks of code
8/// without having to rewrite each clause multiple times.
9macro_rules! cfg_if {
10    // match if/else chains with a final `else`
11    ($(
12        if #[cfg($($meta:meta),*)] { $($it:item)* }
13    ) else * else {
14        $($it2:item)*
15    }) => {
16        cfg_if! {
17            @__items
18            () ;
19            $( ( ($($meta),*) ($($it)*) ), )*
20            ( () ($($it2)*) ),
21        }
22    };
23
24    // match if/else chains lacking a final `else`
25    (
26        if #[cfg($($i_met:meta),*)] { $($i_it:item)* }
27        $(
28            else if #[cfg($($e_met:meta),*)] { $($e_it:item)* }
29        )*
30    ) => {
31        cfg_if! {
32            @__items
33            () ;
34            ( ($($i_met),*) ($($i_it)*) ),
35            $( ( ($($e_met),*) ($($e_it)*) ), )*
36            ( () () ),
37        }
38    };
39
40    // Internal and recursive macro to emit all the items
41    //
42    // Collects all the negated `cfg`s in a list at the beginning and after the
43    // semicolon is all the remaining items
44    (@__items ($($not:meta,)*) ; ) => {};
45    (@__items ($($not:meta,)*) ; ( ($($m:meta),*) ($($it:item)*) ),
46     $($rest:tt)*) => {
47        // Emit all items within one block, applying an appropriate #[cfg]. The
48        // #[cfg] will require all `$m` matchers specified and must also negate
49        // all previous matchers.
50        cfg_if! { @__apply cfg(all($($m,)* not(any($($not),*)))), $($it)* }
51
52        // Recurse to emit all other items in `$rest`, and when we do so add all
53        // our `$m` matchers to the list of `$not` matchers as future emissions
54        // will have to negate everything we just matched as well.
55        cfg_if! { @__items ($($not,)* $($m,)*) ; $($rest)* }
56    };
57
58    // Internal macro to Apply a cfg attribute to a list of items
59    (@__apply $m:meta, $($it:item)*) => {
60        $(#[$m] $it)*
61    };
62}
63
64/// Create an internal crate prelude with `core` reexports and common types.
65macro_rules! prelude {
66    () => {
67        mod types;
68
69        /// Frequently-used types that are available on all platforms
70        ///
71        /// We need to reexport the core types so this works with `rust-dep-of-std`.
72        mod prelude {
73            // Exports from `core`
74            #[allow(unused_imports)]
75            pub(crate) use core::clone::Clone;
76            #[allow(unused_imports)]
77            pub(crate) use core::default::Default;
78            #[allow(unused_imports)]
79            pub(crate) use core::marker::{
80                Copy,
81                Send,
82                Sync,
83            };
84            #[allow(unused_imports)]
85            pub(crate) use core::option::Option;
86            #[allow(unused_imports)]
87            pub(crate) use core::prelude::v1::derive;
88            #[allow(unused_imports)]
89            pub(crate) use core::{
90                cfg,
91                fmt,
92                hash,
93                iter,
94                mem,
95                ptr,
96            };
97
98            #[allow(unused_imports)]
99            pub(crate) use fmt::Debug;
100            #[allow(unused_imports)]
101            pub(crate) use mem::{
102                align_of,
103                align_of_val,
104                size_of,
105                size_of_val,
106            };
107
108            #[allow(unused_imports)]
109            pub(crate) use crate::types::{
110                CEnumRepr,
111                Padding,
112            };
113            // Commonly used types defined in this crate
114            #[allow(unused_imports)]
115            pub(crate) use crate::{
116                c_char,
117                c_double,
118                c_float,
119                c_int,
120                c_long,
121                c_longlong,
122                c_short,
123                c_uchar,
124                c_uint,
125                c_ulong,
126                c_ulonglong,
127                c_ushort,
128                c_void,
129                intptr_t,
130                size_t,
131                ssize_t,
132                uintptr_t,
133            };
134        }
135    };
136}
137
138/// Implement `Clone` and `Copy` for a struct, as well as `Debug`, `Eq`, `Hash`, and
139/// `PartialEq` if the `extra_traits` feature is enabled.
140///
141/// Use [`s_no_extra_traits`] for structs where the `extra_traits` feature does not
142/// make sense, and for unions.
143macro_rules! s {
144    ($(
145        $(#[$attr:meta])*
146        $pub:vis $t:ident $i:ident { $($field:tt)* }
147    )*) => ($(
148        s!(it: $(#[$attr])* $pub $t $i { $($field)* });
149    )*);
150
151    (it: $(#[$attr:meta])* $pub:vis union $i:ident { $($field:tt)* }) => (
152        compile_error!("unions cannot derive extra traits, use s_no_extra_traits instead");
153    );
154
155    (it: $(#[$attr:meta])* $pub:vis struct $i:ident { $($field:tt)* }) => (
156        __item! {
157            #[repr(C)]
158            #[::core::prelude::v1::derive(
159                ::core::clone::Clone,
160                ::core::marker::Copy,
161                ::core::fmt::Debug,
162            )]
163            #[cfg_attr(
164                feature = "extra_traits",
165                ::core::prelude::v1::derive(Eq, Hash, PartialEq)
166            )]
167            #[allow(deprecated)]
168            $(#[$attr])*
169            $pub struct $i { $($field)* }
170        }
171    );
172}
173
174/// Implement `Clone` and `Copy` for a tuple struct, as well as `Debug`, `Eq`, `Hash`,
175/// and `PartialEq` if the `extra_traits` feature is enabled.
176///
177/// This is the same as [`s`] but works for tuple structs.
178macro_rules! s_paren {
179    ($(
180        $(#[$attr:meta])*
181        pub struct $i:ident ( $($field:tt)* );
182    )*) => ($(
183        __item! {
184            #[cfg_attr(
185                feature = "extra_traits",
186                ::core::prelude::v1::derive(Eq, Hash, PartialEq)
187            )]
188            #[::core::prelude::v1::derive(
189                ::core::clone::Clone,
190                ::core::marker::Copy,
191                ::core::fmt::Debug,
192            )]
193            $(#[$attr])*
194            pub struct $i ( $($field)* );
195        }
196    )*);
197}
198
199/// Implement `Clone`, `Copy`, and `Debug` since those can be derived, but exclude `PartialEq`,
200/// `Eq`, and `Hash`.
201///
202/// Most items will prefer to use [`s`].
203macro_rules! s_no_extra_traits {
204    ($(
205        $(#[$attr:meta])*
206        $pub:vis $t:ident $i:ident { $($field:tt)* }
207    )*) => ($(
208        s_no_extra_traits!(it: $(#[$attr])* $pub $t $i { $($field)* });
209    )*);
210
211    (it: $(#[$attr:meta])* $pub:vis union $i:ident { $($field:tt)* }) => (
212        __item! {
213            #[repr(C)]
214            #[::core::prelude::v1::derive(::core::clone::Clone, ::core::marker::Copy)]
215            $(#[$attr])*
216            $pub union $i { $($field)* }
217        }
218
219        impl ::core::fmt::Debug for $i {
220            fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
221                f.debug_struct(::core::stringify!($i)).finish_non_exhaustive()
222            }
223        }
224    );
225
226    (it: $(#[$attr:meta])* $pub:vis struct $i:ident { $($field:tt)* }) => (
227        __item! {
228            #[repr(C)]
229            #[::core::prelude::v1::derive(
230                ::core::clone::Clone,
231                ::core::marker::Copy,
232                ::core::fmt::Debug,
233            )]
234            $(#[$attr])*
235            $pub struct $i { $($field)* }
236        }
237    );
238}
239
240/// Create an uninhabited type that can't be constructed. It implements `Debug`, `Clone`,
241/// and `Copy`, but these aren't meaningful for extern types so they should eventually
242/// be removed.
243///
244/// Really what we want here is something that also can't be named without indirection (in
245/// ADTs or function signatures), but this doesn't exist.
246macro_rules! extern_ty {
247    ($(
248        $(#[$attr:meta])*
249        pub enum $i:ident {}
250    )*) => ($(
251        $(#[$attr])*
252        // FIXME(1.0): the type is uninhabited so these traits are unreachable and could be
253        // removed.
254        #[::core::prelude::v1::derive(
255            ::core::clone::Clone,
256            ::core::marker::Copy,
257            ::core::fmt::Debug,
258        )]
259        pub enum $i { }
260    )*);
261}
262
263/// Implement `Clone` and `Copy` for an enum, as well as `Debug`, `Eq`, `Hash`, and
264/// `PartialEq` if the `extra_traits` feature is enabled.
265// FIXME(#4419): Replace all uses of `e!` with `c_enum!`
266macro_rules! e {
267    ($(
268        $(#[$attr:meta])*
269        pub enum $i:ident { $($field:tt)* }
270    )*) => ($(
271        __item! {
272            #[cfg_attr(
273                feature = "extra_traits",
274                ::core::prelude::v1::derive(Eq, Hash, PartialEq)
275            )]
276            #[::core::prelude::v1::derive(
277                ::core::clone::Clone,
278                ::core::marker::Copy,
279                ::core::fmt::Debug,
280            )]
281            $(#[$attr])*
282            pub enum $i { $($field)* }
283        }
284    )*);
285}
286
287/// Represent a C enum as Rust constants and a type.
288///
289/// C enums can't soundly be mapped to Rust enums since C enums are allowed to have duplicates or
290/// unlisted values, but this is UB in Rust. This enum doesn't implement any traits, its main
291/// purpose is to calculate the correct enum values.
292///
293/// Use the magic name `#anon` if the C enum doesn't create a type.
294///
295/// See <https://github.com/rust-lang/libc/issues/4419> for more.
296macro_rules! c_enum {
297    // Matcher for multiple enums
298    ($(
299        $(#[repr($repr:ty)])?
300        pub enum $($ty_name:ident)? $(#$anon:ident)? {
301            $($vis:vis $variant:ident $(= $value:expr)?,)+
302        }
303    )+) => {
304        $(c_enum!(@single;
305            $(#[repr($repr)])?
306            pub enum $($ty_name)? $(#$anon)? {
307                $($vis $variant $(= $value)?,)+
308            }
309        );)+
310    };
311
312    // Matcher for a single enum
313    (@single;
314        $(#[repr($repr:ty)])?
315        pub enum $ty_name:ident {
316            $($vis:vis $variant:ident $(= $value:expr)?,)+
317        }
318    ) => {
319        pub type $ty_name = c_enum!(@ty $($repr)?);
320        c_enum! {
321            @variant;
322            ty: $ty_name;
323            default: 0;
324            variants: [$($vis $variant $(= $value)?,)+]
325        }
326    };
327
328    // Matcher for a single anonymous enum
329    (@single;
330        $(#[repr($repr:ty)])?
331        pub enum #anon {
332            $($vis:vis $variant:ident $(= $value:expr)?,)+
333        }
334    ) => {
335        c_enum! {
336            @variant;
337            ty: c_enum!(@ty $($repr)?);
338            default: 0;
339            variants: [$($vis $variant $(= $value)?,)+]
340        }
341    };
342
343    // Matcher for variants: eats a single variant then recurses with the rest
344    (@variant; ty: $_ty_name:ty; default: $_idx:expr; variants: []) => { /* end of the chain */ };
345    (
346        @variant;
347        ty: $ty_name:ty;
348        default: $default_val:expr;
349        variants: [
350            $vis:vis $variant:ident $(= $value:expr)?,
351            $($tail:tt)*
352        ]
353    ) => {
354        $vis const $variant: $ty_name = {
355            #[allow(unused_variables)]
356            let r = $default_val;
357            $(let r = $value;)?
358            r
359        };
360
361        // The next value is always one more than the previous value, unless
362        // set explicitly.
363        c_enum! {
364            @variant;
365            ty: $ty_name;
366            default: $variant + 1;
367            variants: [$($tail)*]
368        }
369    };
370
371    // Use a specific type if provided, otherwise default to `CEnumRepr`
372    (@ty $repr:ty) => { $repr };
373    (@ty) => { $crate::prelude::CEnumRepr };
374}
375
376/// Define a `unsafe` function.
377macro_rules! f {
378    ($(
379        $(#[$attr:meta])*
380        // Less than ideal hack to match either `fn` or `const fn`.
381        pub $(fn $i:ident)? $(const fn $const_i:ident)?
382        ($($arg:ident: $argty:ty),* $(,)*) -> $ret:ty
383            $body:block
384    )+) => {$(
385        #[inline]
386        $(#[$attr])*
387        pub $(unsafe extern "C" fn $i)? $(const unsafe extern "C" fn $const_i)?
388        ($($arg: $argty),*) -> $ret
389            $body
390    )+};
391}
392
393/// Define a safe function.
394macro_rules! safe_f {
395    ($(
396        $(#[$attr:meta])*
397        // Less than ideal hack to match either `fn` or `const fn`.
398        pub $(fn $i:ident)? $(const fn $const_i:ident)?
399        ($($arg:ident: $argty:ty),* $(,)*) -> $ret:ty
400            $body:block
401    )+) => {$(
402        #[inline]
403        $(#[$attr])*
404        pub $(extern "C" fn $i)? $(const extern "C" fn $const_i)?
405        ($($arg: $argty),*) -> $ret
406            $body
407    )+};
408}
409
410macro_rules! __item {
411    ($i:item) => {
412        $i
413    };
414}
415
416// This macro is used to deprecate items that should be accessed via the mach2 crate
417macro_rules! deprecated_mach {
418    (pub const $id:ident: $ty:ty = $expr:expr;) => {
419        #[deprecated(
420            since = "0.2.55",
421            note = "Use the `mach2` crate instead",
422        )]
423        #[allow(deprecated)]
424        pub const $id: $ty = $expr;
425    };
426    ($(pub const $id:ident: $ty:ty = $expr:expr;)*) => {
427        $(
428            deprecated_mach!(
429                pub const $id: $ty = $expr;
430            );
431        )*
432    };
433    (pub type $id:ident = $ty:ty;) => {
434        #[deprecated(
435            since = "0.2.55",
436            note = "Use the `mach2` crate instead",
437        )]
438        #[allow(deprecated)]
439        pub type $id = $ty;
440    };
441    ($(pub type $id:ident = $ty:ty;)*) => {
442        $(
443            deprecated_mach!(
444                pub type $id = $ty;
445            );
446        )*
447    }
448}
449
450/// Polyfill for std's `offset_of`.
451// FIXME(msrv): stabilized in std in 1.77
452macro_rules! offset_of {
453    ($Ty:path, $field:ident) => {{
454        // Taken from bytemuck, avoids accidentally calling on deref
455        #[allow(clippy::unneeded_field_pattern)]
456        let $Ty { $field: _, .. };
457        let data = core::mem::MaybeUninit::<$Ty>::uninit();
458        let ptr = data.as_ptr();
459        // SAFETY: computed address is inbounds since we have a stack alloc for T
460        let fptr = unsafe { core::ptr::addr_of!((*ptr).$field) };
461        let off = (fptr as usize).checked_sub(ptr as usize).unwrap();
462        assert!(off <= core::mem::size_of::<$Ty>());
463        off
464    }};
465}
466
467#[cfg(test)]
468mod tests {
469    use core::any::TypeId;
470
471    use crate::types::CEnumRepr;
472
473    #[test]
474    fn c_enum_basic() {
475        // By default, variants get sequential values.
476        c_enum! {
477            pub enum e {
478                VAR0,
479                VAR1,
480                VAR2,
481            }
482
483            // Also check enums that don't create a type.
484            pub enum #anon {
485                ANON0,
486                ANON1,
487                ANON2,
488            }
489        }
490
491        assert_eq!(TypeId::of::<e>(), TypeId::of::<CEnumRepr>());
492        assert_eq!(VAR0, 0 as CEnumRepr);
493        assert_eq!(VAR1, 1 as CEnumRepr);
494        assert_eq!(VAR2, 2 as CEnumRepr);
495
496        assert_eq!(type_id_of_val(&ANON0), TypeId::of::<CEnumRepr>());
497        assert_eq!(ANON0, 0 as CEnumRepr);
498        assert_eq!(ANON1, 1 as CEnumRepr);
499        assert_eq!(ANON2, 2 as CEnumRepr);
500    }
501
502    #[test]
503    fn c_enum_repr() {
504        // Check specifying the integer representation
505        c_enum! {
506            #[repr(u16)]
507            pub enum e {
508                VAR0,
509            }
510
511            #[repr(u16)]
512            pub enum #anon {
513                ANON0,
514            }
515        }
516
517        assert_eq!(TypeId::of::<e>(), TypeId::of::<u16>());
518        assert_eq!(VAR0, 0_u16);
519
520        assert_eq!(type_id_of_val(&ANON0), TypeId::of::<u16>());
521        assert_eq!(ANON0, 0_u16);
522    }
523
524    #[test]
525    fn c_enum_set_value() {
526        // Setting an explicit value resets the count.
527        c_enum! {
528            pub enum e {
529                VAR2 = 2,
530                VAR3,
531                VAR4,
532            }
533        }
534
535        assert_eq!(VAR2, 2 as CEnumRepr);
536        assert_eq!(VAR3, 3 as CEnumRepr);
537        assert_eq!(VAR4, 4 as CEnumRepr);
538    }
539
540    #[test]
541    fn c_enum_multiple_set_value() {
542        // C enums always take one more than the previous value, unless set to a specific
543        // value. Duplicates are allowed.
544        c_enum! {
545            pub enum e {
546                VAR0,
547                VAR2_0 = 2,
548                VAR3_0,
549                VAR4_0,
550                VAR2_1 = 2,
551                VAR3_1,
552                VAR4_1,
553            }
554        }
555
556        assert_eq!(VAR0, 0 as CEnumRepr);
557        assert_eq!(VAR2_0, 2 as CEnumRepr);
558        assert_eq!(VAR3_0, 3 as CEnumRepr);
559        assert_eq!(VAR4_0, 4 as CEnumRepr);
560        assert_eq!(VAR2_1, 2 as CEnumRepr);
561        assert_eq!(VAR3_1, 3 as CEnumRepr);
562        assert_eq!(VAR4_1, 4 as CEnumRepr);
563    }
564
565    #[test]
566    fn c_enum_vis() {
567        mod priv1 {
568            c_enum! {
569                #[repr(u8)]
570                pub enum e1 {
571                    PRIV_ON_1 = 10,
572                    // Variant should still be usable within its visibility
573                    pub PUB1 = PRIV_ON_1 * 2,
574                }
575            }
576        }
577        mod priv2 {
578            c_enum! {
579                #[repr(u16)]
580                pub enum e2 {
581                    pub PRIV_ON_1 = 42,
582                    pub PUB2 = PRIV_ON_1 * 2,
583                }
584            }
585        }
586
587        use priv1::*;
588        use priv2::*;
589
590        assert_eq!(TypeId::of::<e1>(), TypeId::of::<u8>());
591        assert_eq!(TypeId::of::<e2>(), TypeId::of::<u16>());
592        assert_eq!(PUB1, 10u8 * 2);
593        assert_eq!(PUB2, 42u16 * 2);
594        // Verify that the default is private. If `PRIV_ON_1` was actually public in `priv1`, this
595        // would be an ambiguous import and/or type mismatch error.
596        assert_eq!(PRIV_ON_1, 42u16);
597    }
598
599    fn type_id_of_val<T: 'static>(_: &T) -> TypeId {
600        TypeId::of::<T>()
601    }
602
603    #[test]
604    fn test_offset_of() {
605        #[repr(C)]
606        struct Off1 {
607            a: u8,
608            b: u32,
609            c: Off2,
610            d: u64,
611        }
612
613        #[repr(C)]
614        #[repr(align(128))]
615        struct Off2 {}
616
617        assert_eq!(core::mem::offset_of!(Off1, a), offset_of!(Off1, a));
618        assert_eq!(core::mem::offset_of!(Off1, b), offset_of!(Off1, b));
619        assert_eq!(core::mem::offset_of!(Off1, c), offset_of!(Off1, c));
620        assert_eq!(core::mem::offset_of!(Off1, d), offset_of!(Off1, d));
621    }
622}
623
624#[cfg(test)]
625#[allow(unused)]
626mod macro_checks {
627    s! {
628        pub struct S1 {
629            pub a: u32,
630            b: u32,
631        }
632
633        struct S1Priv {
634            pub a: u32,
635            b: u32,
636        }
637    }
638
639    s_no_extra_traits! {
640        pub struct S2 {
641            pub a: u32,
642            b: u32,
643        }
644
645        struct S2Priv {
646            pub a: u32,
647            b: u32,
648        }
649
650        pub union U2 {
651            pub a: u32,
652            b: f32,
653        }
654
655        union U2Priv {
656            pub a: u32,
657            b: f32,
658        }
659    }
660}