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`, `Copy`, and `Debug` for one or more structs, as well as `PartialEq`, `Eq`,
139/// and `Hash` if the `extra_traits` feature is enabled.
140///
141/// Also mark the type with `repr(C)`.
142///
143/// Use [`s_no_extra_traits`] for structs where the `extra_traits` feature does not
144/// make sense, and for unions.
145macro_rules! s {
146    ($(
147        $(#[$attr:meta])*
148        $pub:vis $t:ident $i:ident { $($field:tt)* }
149    )*) => ($(
150        s!(it: $(#[$attr])* $pub $t $i { $($field)* });
151    )*);
152
153    (it: $(#[$attr:meta])* $pub:vis union $i:ident { $($field:tt)* }) => (
154        compile_error!("unions cannot derive extra traits, use s_no_extra_traits instead");
155    );
156
157    (it: $(#[$attr:meta])* $pub:vis struct $i:ident { $($field:tt)* }) => (
158        #[repr(C)]
159        #[::core::prelude::v1::derive(
160            ::core::clone::Clone,
161            ::core::marker::Copy,
162            ::core::fmt::Debug,
163        )]
164        #[cfg_attr(
165            feature = "extra_traits",
166            ::core::prelude::v1::derive(PartialEq, Eq, Hash)
167        )]
168        #[allow(deprecated)]
169        $(#[$attr])*
170        $pub struct $i { $($field)* }
171    );
172}
173
174/// Implement `Clone`, `Copy`, and `Debug` for a tuple struct, as well as `PartialEq`, `Eq`,
175/// and `Hash` if the `extra_traits` feature is enabled.
176///
177/// Unlike `s!`, this does *not* mark the type with `repr(C)`. Users should provide their own
178/// `repr` attribute via `$attr` as necessary.
179macro_rules! s_paren {
180    ($(
181        $(#[$attr:meta])*
182        $pub:vis struct $i:ident ( $($field:tt)* );
183    )*) => ($(
184        #[::core::prelude::v1::derive(
185            ::core::clone::Clone,
186            ::core::marker::Copy,
187            ::core::fmt::Debug,
188        )]
189        #[cfg_attr(
190            feature = "extra_traits",
191            ::core::prelude::v1::derive(PartialEq, Eq, Hash)
192        )]
193        $(#[$attr])*
194        $pub struct $i ( $($field)* );
195    )*);
196}
197
198/// Implement `Clone`, `Copy`, and `Debug` for one or more structs/unions, but exclude `PartialEq`,
199/// `Eq`, and `Hash`.
200///
201/// Also mark the type with `repr(C)`.
202///
203/// Most structs will prefer to use [`s`].
204macro_rules! s_no_extra_traits {
205    ($(
206        $(#[$attr:meta])*
207        $pub:vis $t:ident $i:ident { $($field:tt)* }
208    )*) => ($(
209        s_no_extra_traits!(it: $(#[$attr])* $pub $t $i { $($field)* });
210    )*);
211
212    (it: $(#[$attr:meta])* $pub:vis union $i:ident { $($field:tt)* }) => (
213        #[repr(C)]
214        #[::core::prelude::v1::derive(
215            ::core::clone::Clone,
216            ::core::marker::Copy,
217        )]
218        $(#[$attr])*
219        $pub union $i { $($field)* }
220
221        impl ::core::fmt::Debug for $i {
222            fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
223                f.debug_struct(::core::stringify!($i)).finish_non_exhaustive()
224            }
225        }
226    );
227
228    (it: $(#[$attr:meta])* $pub:vis struct $i:ident { $($field:tt)* }) => (
229        #[repr(C)]
230        #[::core::prelude::v1::derive(
231            ::core::clone::Clone,
232            ::core::marker::Copy,
233            ::core::fmt::Debug,
234        )]
235        $(#[$attr])*
236        $pub struct $i { $($field)* }
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        #[cfg_attr(
272            feature = "extra_traits",
273            ::core::prelude::v1::derive(Eq, Hash, PartialEq)
274        )]
275        #[::core::prelude::v1::derive(
276            ::core::clone::Clone,
277            ::core::marker::Copy,
278            ::core::fmt::Debug,
279        )]
280        $(#[$attr])*
281        pub enum $i { $($field)* }
282    )*);
283}
284
285/// Represent a C enum as Rust constants and a type.
286///
287/// C enums can't soundly be mapped to Rust enums since C enums are allowed to have duplicates or
288/// unlisted values, but this is UB in Rust. This enum doesn't implement any traits, its main
289/// purpose is to calculate the correct enum values.
290///
291/// Use the magic name `#anon` if the C enum doesn't create a type.
292///
293/// See <https://github.com/rust-lang/libc/issues/4419> for more.
294macro_rules! c_enum {
295    // Matcher for multiple enums
296    ($(
297        $(#[repr($repr:ty)])?
298        pub enum $($ty_name:ident)? $(#$anon:ident)? {
299            $($vis:vis $variant:ident $(= $value:expr)?,)+
300        }
301    )+) => {
302        $(c_enum!(@single;
303            $(#[repr($repr)])?
304            pub enum $($ty_name)? $(#$anon)? {
305                $($vis $variant $(= $value)?,)+
306            }
307        );)+
308    };
309
310    // Matcher for a single enum
311    (@single;
312        $(#[repr($repr:ty)])?
313        pub enum $ty_name:ident {
314            $($vis:vis $variant:ident $(= $value:expr)?,)+
315        }
316    ) => {
317        pub type $ty_name = c_enum!(@ty $($repr)?);
318        c_enum! {
319            @variant;
320            ty: $ty_name;
321            default: 0;
322            variants: [$($vis $variant $(= $value)?,)+]
323        }
324    };
325
326    // Matcher for a single anonymous enum
327    (@single;
328        $(#[repr($repr:ty)])?
329        pub enum #anon {
330            $($vis:vis $variant:ident $(= $value:expr)?,)+
331        }
332    ) => {
333        c_enum! {
334            @variant;
335            ty: c_enum!(@ty $($repr)?);
336            default: 0;
337            variants: [$($vis $variant $(= $value)?,)+]
338        }
339    };
340
341    // Matcher for variants: eats a single variant then recurses with the rest
342    (@variant; ty: $_ty_name:ty; default: $_idx:expr; variants: []) => { /* end of the chain */ };
343    (
344        @variant;
345        ty: $ty_name:ty;
346        default: $default_val:expr;
347        variants: [
348            $vis:vis $variant:ident $(= $value:expr)?,
349            $($tail:tt)*
350        ]
351    ) => {
352        $vis const $variant: $ty_name = {
353            #[allow(unused_variables)]
354            let r = $default_val;
355            $(let r = $value;)?
356            r
357        };
358
359        // The next value is always one more than the previous value, unless
360        // set explicitly.
361        c_enum! {
362            @variant;
363            ty: $ty_name;
364            default: $variant + 1;
365            variants: [$($tail)*]
366        }
367    };
368
369    // Use a specific type if provided, otherwise default to `CEnumRepr`
370    (@ty $repr:ty) => { $repr };
371    (@ty) => { $crate::prelude::CEnumRepr };
372}
373
374/// Define a `unsafe` function.
375macro_rules! f {
376    ($(
377        $(#[$attr:meta])*
378        // Less than ideal hack to match either `fn` or `const fn`.
379        pub $(fn $i:ident)? $(const fn $const_i:ident)?
380        ($($arg:ident: $argty:ty),* $(,)*) -> $ret:ty
381            $body:block
382    )+) => {$(
383        #[inline]
384        $(#[$attr])*
385        pub $(unsafe extern "C" fn $i)? $(const unsafe extern "C" fn $const_i)?
386        ($($arg: $argty),*) -> $ret
387            $body
388    )+};
389}
390
391/// Define a safe function.
392macro_rules! safe_f {
393    ($(
394        $(#[$attr:meta])*
395        // Less than ideal hack to match either `fn` or `const fn`.
396        pub $(fn $i:ident)? $(const fn $const_i:ident)?
397        ($($arg:ident: $argty:ty),* $(,)*) -> $ret:ty
398            $body:block
399    )+) => {$(
400        #[inline]
401        $(#[$attr])*
402        pub $(extern "C" fn $i)? $(const extern "C" fn $const_i)?
403        ($($arg: $argty),*) -> $ret
404            $body
405    )+};
406}
407
408// This macro is used to deprecate items that should be accessed via the mach2 crate
409macro_rules! deprecated_mach {
410    (pub const $id:ident: $ty:ty = $expr:expr;) => {
411        #[deprecated(
412            since = "0.2.55",
413            note = "Use the `mach2` crate instead",
414        )]
415        #[allow(deprecated)]
416        pub const $id: $ty = $expr;
417    };
418    ($(pub const $id:ident: $ty:ty = $expr:expr;)*) => {
419        $(
420            deprecated_mach!(
421                pub const $id: $ty = $expr;
422            );
423        )*
424    };
425    (pub type $id:ident = $ty:ty;) => {
426        #[deprecated(
427            since = "0.2.55",
428            note = "Use the `mach2` crate instead",
429        )]
430        #[allow(deprecated)]
431        pub type $id = $ty;
432    };
433    ($(pub type $id:ident = $ty:ty;)*) => {
434        $(
435            deprecated_mach!(
436                pub type $id = $ty;
437            );
438        )*
439    }
440}
441
442/// Polyfill for std's `offset_of`.
443// FIXME(msrv): stabilized in std in 1.77
444macro_rules! offset_of {
445    ($Ty:path, $field:ident) => {{
446        // Taken from bytemuck, avoids accidentally calling on deref
447        #[allow(clippy::unneeded_field_pattern)]
448        let $Ty { $field: _, .. };
449        let data = core::mem::MaybeUninit::<$Ty>::uninit();
450        let ptr = data.as_ptr();
451        // nested unsafe, see f!
452        #[allow(unused_unsafe)]
453        // SAFETY: computed address is inbounds since we have a stack alloc for T
454        let fptr = unsafe { core::ptr::addr_of!((*ptr).$field) };
455        let off = (fptr as usize).checked_sub(ptr as usize).unwrap();
456        core::assert!(off <= core::mem::size_of::<$Ty>());
457        off
458    }};
459}
460
461#[cfg(test)]
462mod tests {
463    use core::any::TypeId;
464
465    use crate::types::CEnumRepr;
466
467    #[test]
468    fn c_enum_basic() {
469        // By default, variants get sequential values.
470        c_enum! {
471            pub enum e {
472                VAR0,
473                VAR1,
474                VAR2,
475            }
476
477            // Also check enums that don't create a type.
478            pub enum #anon {
479                ANON0,
480                ANON1,
481                ANON2,
482            }
483        }
484
485        assert_eq!(TypeId::of::<e>(), TypeId::of::<CEnumRepr>());
486        assert_eq!(VAR0, 0 as CEnumRepr);
487        assert_eq!(VAR1, 1 as CEnumRepr);
488        assert_eq!(VAR2, 2 as CEnumRepr);
489
490        assert_eq!(type_id_of_val(&ANON0), TypeId::of::<CEnumRepr>());
491        assert_eq!(ANON0, 0 as CEnumRepr);
492        assert_eq!(ANON1, 1 as CEnumRepr);
493        assert_eq!(ANON2, 2 as CEnumRepr);
494    }
495
496    #[test]
497    fn c_enum_repr() {
498        // Check specifying the integer representation
499        c_enum! {
500            #[repr(u16)]
501            pub enum e {
502                VAR0,
503            }
504
505            #[repr(u16)]
506            pub enum #anon {
507                ANON0,
508            }
509        }
510
511        assert_eq!(TypeId::of::<e>(), TypeId::of::<u16>());
512        assert_eq!(VAR0, 0_u16);
513
514        assert_eq!(type_id_of_val(&ANON0), TypeId::of::<u16>());
515        assert_eq!(ANON0, 0_u16);
516    }
517
518    #[test]
519    fn c_enum_set_value() {
520        // Setting an explicit value resets the count.
521        c_enum! {
522            pub enum e {
523                VAR2 = 2,
524                VAR3,
525                VAR4,
526            }
527        }
528
529        assert_eq!(VAR2, 2 as CEnumRepr);
530        assert_eq!(VAR3, 3 as CEnumRepr);
531        assert_eq!(VAR4, 4 as CEnumRepr);
532    }
533
534    #[test]
535    fn c_enum_multiple_set_value() {
536        // C enums always take one more than the previous value, unless set to a specific
537        // value. Duplicates are allowed.
538        c_enum! {
539            pub enum e {
540                VAR0,
541                VAR2_0 = 2,
542                VAR3_0,
543                VAR4_0,
544                VAR2_1 = 2,
545                VAR3_1,
546                VAR4_1,
547            }
548        }
549
550        assert_eq!(VAR0, 0 as CEnumRepr);
551        assert_eq!(VAR2_0, 2 as CEnumRepr);
552        assert_eq!(VAR3_0, 3 as CEnumRepr);
553        assert_eq!(VAR4_0, 4 as CEnumRepr);
554        assert_eq!(VAR2_1, 2 as CEnumRepr);
555        assert_eq!(VAR3_1, 3 as CEnumRepr);
556        assert_eq!(VAR4_1, 4 as CEnumRepr);
557    }
558
559    #[test]
560    fn c_enum_vis() {
561        mod priv1 {
562            c_enum! {
563                #[repr(u8)]
564                pub enum e1 {
565                    PRIV_ON_1 = 10,
566                    // Variant should still be usable within its visibility
567                    pub PUB1 = PRIV_ON_1 * 2,
568                }
569            }
570        }
571        mod priv2 {
572            c_enum! {
573                #[repr(u16)]
574                pub enum e2 {
575                    pub PRIV_ON_1 = 42,
576                    pub PUB2 = PRIV_ON_1 * 2,
577                }
578            }
579        }
580
581        use priv1::*;
582        use priv2::*;
583
584        assert_eq!(TypeId::of::<e1>(), TypeId::of::<u8>());
585        assert_eq!(TypeId::of::<e2>(), TypeId::of::<u16>());
586        assert_eq!(PUB1, 10u8 * 2);
587        assert_eq!(PUB2, 42u16 * 2);
588        // Verify that the default is private. If `PRIV_ON_1` was actually public in `priv1`, this
589        // would be an ambiguous import and/or type mismatch error.
590        assert_eq!(PRIV_ON_1, 42u16);
591    }
592
593    fn type_id_of_val<T: 'static>(_: &T) -> TypeId {
594        TypeId::of::<T>()
595    }
596
597    #[test]
598    fn test_offset_of() {
599        #[repr(C)]
600        struct Off1 {
601            a: u8,
602            b: u32,
603            c: Off2,
604            d: u64,
605        }
606
607        #[repr(C)]
608        #[repr(align(128))]
609        struct Off2 {}
610
611        assert_eq!(core::mem::offset_of!(Off1, a), offset_of!(Off1, a));
612        assert_eq!(core::mem::offset_of!(Off1, b), offset_of!(Off1, b));
613        assert_eq!(core::mem::offset_of!(Off1, c), offset_of!(Off1, c));
614        assert_eq!(core::mem::offset_of!(Off1, d), offset_of!(Off1, d));
615    }
616}
617
618#[cfg(test)]
619#[allow(unused)]
620mod macro_checks {
621    s! {
622        pub struct S1 {
623            pub a: u32,
624            b: u32,
625        }
626
627        struct S1Priv {
628            pub a: u32,
629            b: u32,
630        }
631    }
632
633    s_no_extra_traits! {
634        pub struct S2 {
635            pub a: u32,
636            b: u32,
637        }
638
639        struct S2Priv {
640            pub a: u32,
641            b: u32,
642        }
643
644        pub union U2 {
645            pub a: u32,
646            b: f32,
647        }
648
649        union U2Priv {
650            pub a: u32,
651            b: f32,
652        }
653    }
654}