Skip to main content

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                assert,
91                cfg,
92                debug_assert,
93                fmt,
94                hash,
95                iter,
96                mem,
97                ptr,
98            };
99
100            #[allow(unused_imports)]
101            pub(crate) use fmt::Debug;
102            #[allow(unused_imports)]
103            pub(crate) use mem::{
104                align_of,
105                align_of_val,
106                size_of,
107                size_of_val,
108            };
109
110            #[allow(unused_imports)]
111            #[cfg(any(target_os = "linux", target_os = "android", target_os = "l4re"))]
112            pub(crate) use crate::types::u32_cast_ioctl;
113            #[allow(unused_imports)]
114            pub(crate) use crate::types::{
115                replace_array_items,
116                u16_cast_short,
117                u32_cast_int,
118                u32_cast_long,
119                u8_slice_cast_char_slice,
120                ulong_cast_int,
121                ulong_cast_uint,
122                CEnumRepr,
123                Padding,
124            };
125            // Commonly used types defined in this crate
126            #[allow(unused_imports)]
127            pub(crate) use crate::{
128                c_char,
129                c_double,
130                c_float,
131                c_int,
132                c_long,
133                c_longlong,
134                c_short,
135                c_uchar,
136                c_uint,
137                c_ulong,
138                c_ulonglong,
139                c_ushort,
140                c_void,
141                intptr_t,
142                size_t,
143                ssize_t,
144                uintptr_t,
145            };
146        }
147    };
148}
149
150/// Implement `Clone`, `Copy`, and `Debug` for one or more structs, as well as `PartialEq`, `Eq`,
151/// and `Hash` if the `extra_traits` feature is enabled.
152///
153/// Also mark the type with `repr(C)`.
154///
155/// Use [`s_no_extra_traits`] for structs where the `extra_traits` feature does not
156/// make sense, and for unions.
157macro_rules! s {
158    ($(
159        $(#[$attr:meta])*
160        $pub:vis $t:ident $i:ident { $($field:tt)* }
161    )*) => ($(
162        s!(it: $(#[$attr])* $pub $t $i { $($field)* });
163    )*);
164
165    (it: $(#[$attr:meta])* $pub:vis union $i:ident { $($field:tt)* }) => (
166        compile_error!("unions cannot derive extra traits, use s_no_extra_traits instead");
167    );
168
169    (it: $(#[$attr:meta])* $pub:vis struct $i:ident { $($field:tt)* }) => (
170        #[repr(C)]
171        #[::core::prelude::v1::derive(
172            ::core::clone::Clone,
173            ::core::marker::Copy,
174            ::core::fmt::Debug,
175        )]
176        #[cfg_attr(
177            feature = "extra_traits",
178            ::core::prelude::v1::derive(PartialEq, Eq, Hash)
179        )]
180        #[allow(deprecated)]
181        $(#[$attr])*
182        $pub struct $i { $($field)* }
183    );
184}
185
186/// Implement `Clone`, `Copy`, and `Debug` for a tuple struct, as well as `PartialEq`, `Eq`,
187/// and `Hash` if the `extra_traits` feature is enabled.
188///
189/// Unlike `s!`, this does *not* mark the type with `repr(C)`. Users should provide their own
190/// `repr` attribute via `$attr` as necessary.
191macro_rules! s_paren {
192    ($(
193        $(#[$attr:meta])*
194        $pub:vis struct $i:ident ( $($field:tt)* );
195    )*) => ($(
196        #[::core::prelude::v1::derive(
197            ::core::clone::Clone,
198            ::core::marker::Copy,
199            ::core::fmt::Debug,
200        )]
201        #[cfg_attr(
202            feature = "extra_traits",
203            ::core::prelude::v1::derive(PartialEq, Eq, Hash)
204        )]
205        $(#[$attr])*
206        $pub struct $i ( $($field)* );
207    )*);
208}
209
210/// Implement `Clone`, `Copy`, and `Debug` for one or more structs/unions, but exclude `PartialEq`,
211/// `Eq`, and `Hash`.
212///
213/// Also mark the type with `repr(C)`.
214///
215/// Most structs will prefer to use [`s`].
216macro_rules! s_no_extra_traits {
217    ($(
218        $(#[$attr:meta])*
219        $pub:vis $t:ident $i:ident { $($field:tt)* }
220    )*) => ($(
221        s_no_extra_traits!(it: $(#[$attr])* $pub $t $i { $($field)* });
222    )*);
223
224    (it: $(#[$attr:meta])* $pub:vis union $i:ident { $($field:tt)* }) => (
225        #[repr(C)]
226        #[::core::prelude::v1::derive(
227            ::core::clone::Clone,
228            ::core::marker::Copy,
229        )]
230        $(#[$attr])*
231        $pub union $i { $($field)* }
232
233        impl ::core::fmt::Debug for $i {
234            fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
235                f.debug_struct(::core::stringify!($i)).finish_non_exhaustive()
236            }
237        }
238    );
239
240    (it: $(#[$attr:meta])* $pub:vis struct $i:ident { $($field:tt)* }) => (
241        #[repr(C)]
242        #[::core::prelude::v1::derive(
243            ::core::clone::Clone,
244            ::core::marker::Copy,
245            ::core::fmt::Debug,
246        )]
247        $(#[$attr])*
248        $pub struct $i { $($field)* }
249    );
250}
251
252/// Create an uninhabited type that can't be constructed. It implements `Debug`, `Clone`,
253/// and `Copy`, but these aren't meaningful for extern types so they should eventually
254/// be removed.
255///
256/// Really what we want here is something that also can't be named without indirection (in
257/// ADTs or function signatures), but this doesn't exist.
258macro_rules! extern_ty {
259    ($(
260        $(#[$attr:meta])*
261        $vis:vis type $i:ident;
262    )*) => ($(
263        $(#[$attr])*
264        /// This is an extern type ("opaque" or "incomplete" type in C).
265        ///
266        /// <div class="warning">
267        /// This type's current representation allows inspecting some properties, such as via
268        /// <code>size_of</code>, and it is technically possible to construct the type within
269        /// <code>MaybeUninit</code>, However, this <strong>MUST NOT</strong> be relied upon
270        /// because a future version of <code>libc</code> may switch to a proper
271        /// <a href="https://rust-lang.github.io/rfcs/1861-extern-types.html">extern type</a>
272        /// representation when available.
273        /// </div>
274        // ^ unfortunately warning blocks currently don't render markdown so we need to
275        // use raw HTML.
276        //
277        // Representation based on the Nomicon:
278        // <https://doc.rust-lang.org/nomicon/ffi.html#representing-opaque-structs>.
279        //
280        // FIXME(1.0): These traits are unreachable and should be removed.
281        #[::core::prelude::v1::derive(
282            ::core::clone::Clone,
283            ::core::marker::Copy,
284            ::core::fmt::Debug,
285        )]
286        #[repr(C)]
287        $vis struct $i {
288            _data: (),
289            _marker: ::core::marker::PhantomData<(*mut u8, ::core::marker::PhantomPinned)>,
290        }
291    )*);
292}
293
294/// Implement `Clone` and `Copy` for an enum, as well as `Debug`, `Eq`, `Hash`, and
295/// `PartialEq` if the `extra_traits` feature is enabled.
296// FIXME(#4419): Replace all uses of `e!` with `c_enum!`
297macro_rules! e {
298    ($(
299        $(#[$attr:meta])*
300        pub enum $i:ident { $($field:tt)* }
301    )*) => ($(
302        #[cfg_attr(
303            feature = "extra_traits",
304            ::core::prelude::v1::derive(Eq, Hash, PartialEq)
305        )]
306        #[::core::prelude::v1::derive(
307            ::core::clone::Clone,
308            ::core::marker::Copy,
309            ::core::fmt::Debug,
310        )]
311        $(#[$attr])*
312        pub enum $i { $($field)* }
313    )*);
314}
315
316/// Represent a C enum as Rust constants and a type.
317///
318/// C enums can't soundly be mapped to Rust enums since C enums are allowed to have duplicates or
319/// unlisted values, but this is UB in Rust. This enum doesn't implement any traits, its main
320/// purpose is to calculate the correct enum values.
321///
322/// Use the magic name `#anon` if the C enum doesn't create a type.
323///
324/// See <https://github.com/rust-lang/libc/issues/4419> for more.
325macro_rules! c_enum {
326    // Matcher for multiple enums
327    ($(
328        $(#[repr($repr:ty)])?
329        $vis:vis enum $($ty_name:ident)? $(#$anon:ident)? {
330            $($field_vis:vis $variant:ident $(= $value:expr)?,)+
331        }
332    )+) => {
333        $(c_enum!(@single;
334            $(#[repr($repr)])?
335            $vis enum $($ty_name)? $(#$anon)? {
336                $($field_vis $variant $(= $value)?,)+
337            }
338        );)+
339    };
340
341    // Matcher for a single enum
342    (@single;
343        $(#[repr($repr:ty)])?
344        $vis:vis enum $ty_name:ident {
345            $($field_vis:vis $variant:ident $(= $value:expr)?,)+
346        }
347    ) => {
348        $vis type $ty_name = c_enum!(@ty $($repr)?);
349        c_enum! {
350            @variant;
351            ty: $ty_name;
352            default: 0;
353            variants: [$($field_vis $variant $(= $value)?,)+]
354        }
355    };
356
357    // Matcher for a single anonymous enum
358    (@single;
359        $(#[repr($repr:ty)])?
360        $vis:vis enum #anon {
361            $($field_vis:vis $variant:ident $(= $value:expr)?,)+
362        }
363    ) => {
364        c_enum! {
365            @variant;
366            ty: c_enum!(@ty $($repr)?);
367            default: 0;
368            variants: [$($field_vis $variant $(= $value)?,)+]
369        }
370    };
371
372    // Matcher for variants: eats a single variant then recurses with the rest
373    (@variant; ty: $_ty_name:ty; default: $_idx:expr; variants: []) => { /* end of the chain */ };
374    (
375        @variant;
376        ty: $ty_name:ty;
377        default: $default_val:expr;
378        variants: [
379            $field_vis:vis $variant:ident $(= $value:expr)?,
380            $($tail:tt)*
381        ]
382    ) => {
383        $field_vis const $variant: $ty_name = {
384            #[allow(unused_variables)]
385            let r = $default_val;
386            $(let r = $value;)?
387            r
388        };
389
390        // The next value is always one more than the previous value, unless
391        // set explicitly.
392        c_enum! {
393            @variant;
394            ty: $ty_name;
395            default: $variant + 1;
396            variants: [$($tail)*]
397        }
398    };
399
400    // Use a specific type if provided, otherwise default to `CEnumRepr`
401    (@ty $repr:ty) => { $repr };
402    (@ty) => { $crate::prelude::CEnumRepr };
403}
404
405/// Define a `unsafe` function.
406macro_rules! f {
407    ($(
408        $(#[$attr:meta])*
409        pub $(const $($const_dummy:literal)?)? unsafe
410        fn $i:ident ($($arg:ident: $argty:ty),* $(,)?) -> $ret:ty
411            $body:block
412    )+) => {$(
413        #[inline]
414        $(#[$attr])*
415        pub $(const $($const_dummy)?)? unsafe extern "C"
416        fn $i ($($arg: $argty),*) -> $ret
417            $body
418    )+};
419}
420
421/// Define a safe function.
422macro_rules! safe_f {
423    ($(
424        $(#[$attr:meta])*
425        pub $(const $($const_dummy:literal)?)? safe
426        fn $i:ident ($($arg:ident: $argty:ty),* $(,)?) -> $ret:ty
427            $body:block
428    )+) => {$(
429        #[inline]
430        $(#[$attr])*
431        pub $(const $($const_dummy)?)? extern "C"
432        fn $i ($($arg: $argty),*) -> $ret
433            $body
434    )+};
435}
436
437// This macro is used to deprecate items that should be accessed via the mach2 crate
438macro_rules! deprecated_mach {
439    (pub const $id:ident: $ty:ty = $expr:expr;) => {
440        #[deprecated(
441            since = "0.2.55",
442            note = "Use the `mach2` crate instead",
443        )]
444        #[allow(deprecated)]
445        pub const $id: $ty = $expr;
446    };
447    ($(pub const $id:ident: $ty:ty = $expr:expr;)*) => {
448        $(
449            deprecated_mach!(
450                pub const $id: $ty = $expr;
451            );
452        )*
453    };
454    (pub type $id:ident = $ty:ty;) => {
455        #[deprecated(
456            since = "0.2.55",
457            note = "Use the `mach2` crate instead",
458        )]
459        #[allow(deprecated)]
460        pub type $id = $ty;
461    };
462    ($(pub type $id:ident = $ty:ty;)*) => {
463        $(
464            deprecated_mach!(
465                pub type $id = $ty;
466            );
467        )*
468    }
469}
470
471/// Polyfill for std's `offset_of`.
472// FIXME(msrv): stabilized in std in 1.77
473macro_rules! offset_of {
474    ($Ty:path, $field:ident) => {{
475        // Taken from bytemuck, avoids accidentally calling on deref
476        #[allow(clippy::unneeded_wildcard_pattern)]
477        let $Ty { $field: _, .. };
478        let data = core::mem::MaybeUninit::<$Ty>::uninit();
479        let ptr = data.as_ptr();
480        // nested unsafe, see f!
481        #[allow(unused_unsafe)]
482        // SAFETY: computed address is inbounds since we have a stack alloc for T
483        let fptr = unsafe { core::ptr::addr_of!((*ptr).$field) };
484        let off = (fptr as usize).checked_sub(ptr as usize).unwrap();
485        core::assert!(off <= core::mem::size_of::<$Ty>());
486        off
487    }};
488}
489
490#[cfg(test)]
491mod tests {
492    use core::any::TypeId;
493
494    use crate::types::CEnumRepr;
495
496    #[test]
497    fn c_enum_basic() {
498        // By default, variants get sequential values.
499        c_enum! {
500            pub enum e {
501                VAR0,
502                VAR1,
503                VAR2,
504            }
505
506            // Also check enums that don't create a type.
507            pub enum #anon {
508                ANON0,
509                ANON1,
510                ANON2,
511            }
512
513            // No visibility required.
514            enum #anon {
515                ANON3,
516                ANON4,
517                ANON5,
518            }
519        }
520
521        assert_eq!(TypeId::of::<e>(), TypeId::of::<CEnumRepr>());
522        assert_eq!(VAR0, 0 as CEnumRepr);
523        assert_eq!(VAR1, 1 as CEnumRepr);
524        assert_eq!(VAR2, 2 as CEnumRepr);
525
526        assert_eq!(type_id_of_val(&ANON0), TypeId::of::<CEnumRepr>());
527        assert_eq!(ANON0, 0 as CEnumRepr);
528        assert_eq!(ANON1, 1 as CEnumRepr);
529        assert_eq!(ANON2, 2 as CEnumRepr);
530
531        assert_eq!(type_id_of_val(&ANON3), TypeId::of::<CEnumRepr>());
532        assert_eq!(ANON3, 0 as CEnumRepr);
533        assert_eq!(ANON4, 1 as CEnumRepr);
534        assert_eq!(ANON5, 2 as CEnumRepr);
535    }
536
537    #[test]
538    fn c_enum_repr() {
539        // Check specifying the integer representation
540        c_enum! {
541            #[repr(u16)]
542            pub enum e {
543                VAR0,
544            }
545
546            #[repr(u16)]
547            pub enum #anon {
548                ANON0,
549            }
550        }
551
552        assert_eq!(TypeId::of::<e>(), TypeId::of::<u16>());
553        assert_eq!(VAR0, 0_u16);
554
555        assert_eq!(type_id_of_val(&ANON0), TypeId::of::<u16>());
556        assert_eq!(ANON0, 0_u16);
557    }
558
559    #[test]
560    fn c_enum_set_value() {
561        // Setting an explicit value resets the count.
562        c_enum! {
563            pub enum e {
564                VAR2 = 2,
565                VAR3,
566                VAR4,
567            }
568        }
569
570        assert_eq!(VAR2, 2 as CEnumRepr);
571        assert_eq!(VAR3, 3 as CEnumRepr);
572        assert_eq!(VAR4, 4 as CEnumRepr);
573    }
574
575    #[test]
576    fn c_enum_multiple_set_value() {
577        // C enums always take one more than the previous value, unless set to a specific
578        // value. Duplicates are allowed.
579        c_enum! {
580            pub enum e {
581                VAR0,
582                VAR2_0 = 2,
583                VAR3_0,
584                VAR4_0,
585                VAR2_1 = 2,
586                VAR3_1,
587                VAR4_1,
588            }
589        }
590
591        assert_eq!(VAR0, 0 as CEnumRepr);
592        assert_eq!(VAR2_0, 2 as CEnumRepr);
593        assert_eq!(VAR3_0, 3 as CEnumRepr);
594        assert_eq!(VAR4_0, 4 as CEnumRepr);
595        assert_eq!(VAR2_1, 2 as CEnumRepr);
596        assert_eq!(VAR3_1, 3 as CEnumRepr);
597        assert_eq!(VAR4_1, 4 as CEnumRepr);
598    }
599
600    #[test]
601    fn c_enum_vis() {
602        mod priv1 {
603            c_enum! {
604                #[repr(u8)]
605                pub enum e1 {
606                    PRIV_ON_1 = 10,
607                    // Variant should still be usable within its visibility
608                    pub PUB1 = PRIV_ON_1 * 2,
609                }
610            }
611        }
612        mod priv2 {
613            c_enum! {
614                #[repr(u16)]
615                pub enum e2 {
616                    pub PRIV_ON_1 = 42,
617                    pub PUB2 = PRIV_ON_1 * 2,
618                }
619            }
620        }
621
622        use priv1::*;
623        use priv2::*;
624
625        assert_eq!(TypeId::of::<e1>(), TypeId::of::<u8>());
626        assert_eq!(TypeId::of::<e2>(), TypeId::of::<u16>());
627        assert_eq!(PUB1, 10u8 * 2);
628        assert_eq!(PUB2, 42u16 * 2);
629        // Verify that the default is private. If `PRIV_ON_1` was actually public in `priv1`, this
630        // would be an ambiguous import and/or type mismatch error.
631        assert_eq!(PRIV_ON_1, 42u16);
632    }
633
634    fn type_id_of_val<T: 'static>(_: &T) -> TypeId {
635        TypeId::of::<T>()
636    }
637
638    #[test]
639    fn test_offset_of() {
640        #[repr(C)]
641        struct Off1 {
642            a: u8,
643            b: u32,
644            c: Off2,
645            d: u64,
646        }
647
648        #[repr(C)]
649        #[repr(align(128))]
650        struct Off2 {}
651
652        assert_eq!(core::mem::offset_of!(Off1, a), offset_of!(Off1, a));
653        assert_eq!(core::mem::offset_of!(Off1, b), offset_of!(Off1, b));
654        assert_eq!(core::mem::offset_of!(Off1, c), offset_of!(Off1, c));
655        assert_eq!(core::mem::offset_of!(Off1, d), offset_of!(Off1, d));
656    }
657}
658
659#[cfg(test)]
660#[allow(unused)]
661mod macro_checks {
662    s! {
663        pub struct S1 {
664            pub a: u32,
665            b: u32,
666        }
667
668        struct S1Priv {
669            pub a: u32,
670            b: u32,
671        }
672    }
673
674    s_no_extra_traits! {
675        pub struct S2 {
676            pub a: u32,
677            b: u32,
678        }
679
680        struct S2Priv {
681            pub a: u32,
682            b: u32,
683        }
684
685        pub union U2 {
686            pub a: u32,
687            b: f32,
688        }
689
690        union U2Priv {
691            pub a: u32,
692            b: f32,
693        }
694    }
695
696    extern_ty! {
697        type Foo;
698        pub type Bar;
699    }
700}