Coverage Report

Created: 2025-11-11 06:53

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.177/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
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.
9
macro_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.
65
macro_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::{Copy, Send, Sync};
80
            #[allow(unused_imports)]
81
            pub(crate) use core::option::Option;
82
            #[allow(unused_imports)]
83
            pub(crate) use core::prelude::v1::derive;
84
            #[allow(unused_imports)]
85
            pub(crate) use core::{fmt, hash, iter, mem, ptr};
86
87
            #[allow(unused_imports)]
88
            pub(crate) use fmt::Debug;
89
            #[allow(unused_imports)]
90
            pub(crate) use mem::{align_of, align_of_val, size_of, size_of_val};
91
92
            #[allow(unused_imports)]
93
            pub(crate) use crate::types::{CEnumRepr, Padding};
94
            // Commonly used types defined in this crate
95
            #[allow(unused_imports)]
96
            pub(crate) use crate::{
97
                c_char, c_double, c_float, c_int, c_long, c_longlong, c_short, c_uchar, c_uint,
98
                c_ulong, c_ulonglong, c_ushort, c_void, intptr_t, size_t, ssize_t, uintptr_t,
99
            };
100
        }
101
    };
102
}
103
104
/// Implement `Clone` and `Copy` for a struct, as well as `Debug`, `Eq`, `Hash`, and
105
/// `PartialEq` if the `extra_traits` feature is enabled.
106
///
107
/// Use [`s_no_extra_traits`] for structs where the `extra_traits` feature does not
108
/// make sense, and for unions.
109
macro_rules! s {
110
    ($(
111
        $(#[$attr:meta])*
112
        pub $t:ident $i:ident { $($field:tt)* }
113
    )*) => ($(
114
        s!(it: $(#[$attr])* pub $t $i { $($field)* });
115
    )*);
116
117
    (it: $(#[$attr:meta])* pub union $i:ident { $($field:tt)* }) => (
118
        compile_error!("unions cannot derive extra traits, use s_no_extra_traits instead");
119
    );
120
121
    (it: $(#[$attr:meta])* pub struct $i:ident { $($field:tt)* }) => (
122
        __item! {
123
            #[repr(C)]
124
            #[cfg_attr(
125
                feature = "extra_traits",
126
                ::core::prelude::v1::derive(Eq, Hash, PartialEq)
127
            )]
128
            #[::core::prelude::v1::derive(
129
                ::core::clone::Clone,
130
                ::core::marker::Copy,
131
                ::core::fmt::Debug,
132
            )]
133
            #[allow(deprecated)]
134
            $(#[$attr])*
135
            pub struct $i { $($field)* }
136
        }
137
    );
138
}
139
140
/// Implement `Clone` and `Copy` for a tuple struct, as well as `Debug`, `Eq`, `Hash`,
141
/// and `PartialEq` if the `extra_traits` feature is enabled.
142
///
143
/// This is the same as [`s`] but works for tuple structs.
144
macro_rules! s_paren {
145
    ($(
146
        $(#[$attr:meta])*
147
        pub struct $i:ident ( $($field:tt)* );
148
    )*) => ($(
149
        __item! {
150
            #[cfg_attr(
151
                feature = "extra_traits",
152
                ::core::prelude::v1::derive(Eq, Hash, PartialEq)
153
            )]
154
            #[::core::prelude::v1::derive(
155
                ::core::clone::Clone,
156
                ::core::marker::Copy,
157
                ::core::fmt::Debug,
158
            )]
159
            $(#[$attr])*
160
            pub struct $i ( $($field)* );
161
        }
162
    )*);
163
}
164
165
/// Implement `Clone`, `Copy`, and `Debug` since those can be derived, but exclude `PartialEq`,
166
/// `Eq`, and `Hash`.
167
///
168
/// Most items will prefer to use [`s`].
169
macro_rules! s_no_extra_traits {
170
    ($(
171
        $(#[$attr:meta])*
172
        pub $t:ident $i:ident { $($field:tt)* }
173
    )*) => ($(
174
        s_no_extra_traits!(it: $(#[$attr])* pub $t $i { $($field)* });
175
    )*);
176
177
    (it: $(#[$attr:meta])* pub union $i:ident { $($field:tt)* }) => (
178
        __item! {
179
            #[repr(C)]
180
            #[::core::prelude::v1::derive(::core::clone::Clone, ::core::marker::Copy)]
181
            $(#[$attr])*
182
            pub union $i { $($field)* }
183
        }
184
185
        impl ::core::fmt::Debug for $i {
186
0
            fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
187
0
                f.debug_struct(::core::stringify!($i)).finish_non_exhaustive()
188
0
            }
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::__c_anonymous_ifr_ifru 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_ifc_ifcu as core::fmt::Debug>::fmt
Unexecuted instantiation: <libc::unix::linux_like::linux::tpacket_req_u as core::fmt::Debug>::fmt
Unexecuted instantiation: <libc::unix::linux_like::linux::tpacket_bd_header_u 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::linux_uapi::linux::can::__c_anonymous_sockaddr_can_can_addr as core::fmt::Debug>::fmt
189
        }
190
    );
191
192
    (it: $(#[$attr:meta])* pub struct $i:ident { $($field:tt)* }) => (
193
        __item! {
194
            #[repr(C)]
195
            #[::core::prelude::v1::derive(
196
                ::core::clone::Clone,
197
                ::core::marker::Copy,
198
                ::core::fmt::Debug,
199
            )]
200
            $(#[$attr])*
201
            pub struct $i { $($field)* }
202
        }
203
    );
204
}
205
206
/// Specify that an enum should have no traits that aren't specified in the macro
207
/// invocation, i.e. no `Clone` or `Copy`.
208
macro_rules! missing {
209
    ($(
210
        $(#[$attr:meta])*
211
        pub enum $i:ident {}
212
    )*) => ($(
213
        $(#[$attr])*
214
        #[allow(missing_copy_implementations)]
215
        pub enum $i { }
216
    )*);
217
}
218
219
/// Implement `Clone` and `Copy` for an enum, as well as `Debug`, `Eq`, `Hash`, and
220
/// `PartialEq` if the `extra_traits` feature is enabled.
221
// FIXME(#4419): Replace all uses of `e!` with `c_enum!`
222
macro_rules! e {
223
    ($(
224
        $(#[$attr:meta])*
225
        pub enum $i:ident { $($field:tt)* }
226
    )*) => ($(
227
        __item! {
228
            #[cfg_attr(
229
                feature = "extra_traits",
230
                ::core::prelude::v1::derive(Eq, Hash, PartialEq)
231
            )]
232
            #[::core::prelude::v1::derive(
233
                ::core::clone::Clone,
234
                ::core::marker::Copy,
235
                ::core::fmt::Debug,
236
            )]
237
            $(#[$attr])*
238
            pub enum $i { $($field)* }
239
        }
240
    )*);
241
}
242
243
/// Represent a C enum as Rust constants and a type.
244
///
245
/// C enums can't soundly be mapped to Rust enums since C enums are allowed to have duplicates or
246
/// unlisted values, but this is UB in Rust. This enum doesn't implement any traits, its main
247
/// purpose is to calculate the correct enum values.
248
///
249
/// See <https://github.com/rust-lang/libc/issues/4419> for more.
250
macro_rules! c_enum {
251
    ($(
252
        $(#[repr($repr:ty)])?
253
        pub enum $ty_name:ident {
254
            $($variant:ident $(= $value:expr)?,)+
255
        }
256
    )+) => {
257
        $(c_enum!(@expand;
258
            $(#[repr($repr)])?
259
            pub enum $ty_name {
260
                $($variant $(= $value)?,)+
261
            }
262
        );)+
263
    };
264
265
    (@expand;
266
        $(#[repr($repr:ty)])?
267
        pub enum $ty_name:ident {
268
            $($variant:ident $(= $value:expr)?,)+
269
        }
270
    ) => {
271
        pub type $ty_name = c_enum!(@ty $($repr)?);
272
        c_enum!(@one; $ty_name; 0; $($variant $(= $value)?,)+);
273
    };
274
275
    // Matcher for a single variant
276
    (@one; $_ty_name:ident; $_idx:expr;) => {};
277
    (
278
        @one; $ty_name:ident; $default_val:expr;
279
        $variant:ident $(= $value:expr)?,
280
        $($tail:tt)*
281
    ) => {
282
        pub const $variant: $ty_name = {
283
            #[allow(unused_variables)]
284
            let r = $default_val;
285
            $(let r = $value;)?
286
            r
287
        };
288
289
        // The next value is always one more than the previous value, unless
290
        // set explicitly.
291
        c_enum!(@one; $ty_name; $variant + 1; $($tail)*);
292
    };
293
294
    // Use a specific type if provided, otherwise default to `CEnumRepr`
295
    (@ty $repr:ty) => { $repr };
296
    (@ty) => { $crate::prelude::CEnumRepr };
297
}
298
299
/// Define a `unsafe` function.
300
macro_rules! f {
301
    ($(
302
        $(#[$attr:meta])*
303
        // Less than ideal hack to match either `fn` or `const fn`.
304
        pub $(fn $i:ident)? $(const fn $const_i:ident)?
305
        ($($arg:ident: $argty:ty),* $(,)*) -> $ret:ty
306
            $body:block
307
    )+) => {$(
308
        #[inline]
309
        $(#[$attr])*
310
        pub $(unsafe extern "C" fn $i)? $(const unsafe extern "C" fn $const_i)?
311
        ($($arg: $argty),*) -> $ret
312
            $body
313
    )+};
314
}
315
316
/// Define a safe function.
317
macro_rules! safe_f {
318
    ($(
319
        $(#[$attr:meta])*
320
        // Less than ideal hack to match either `fn` or `const fn`.
321
        pub $(fn $i:ident)? $(const fn $const_i:ident)?
322
        ($($arg:ident: $argty:ty),* $(,)*) -> $ret:ty
323
            $body:block
324
    )+) => {$(
325
        #[inline]
326
        $(#[$attr])*
327
        pub $(extern "C" fn $i)? $(const extern "C" fn $const_i)?
328
        ($($arg: $argty),*) -> $ret
329
            $body
330
    )+};
331
}
332
333
macro_rules! __item {
334
    ($i:item) => {
335
        $i
336
    };
337
}
338
339
// This macro is used to deprecate items that should be accessed via the mach2 crate
340
macro_rules! deprecated_mach {
341
    (pub const $id:ident: $ty:ty = $expr:expr;) => {
342
        #[deprecated(
343
            since = "0.2.55",
344
            note = "Use the `mach2` crate instead",
345
        )]
346
        #[allow(deprecated)]
347
        pub const $id: $ty = $expr;
348
    };
349
    ($(pub const $id:ident: $ty:ty = $expr:expr;)*) => {
350
        $(
351
            deprecated_mach!(
352
                pub const $id: $ty = $expr;
353
            );
354
        )*
355
    };
356
    (pub type $id:ident = $ty:ty;) => {
357
        #[deprecated(
358
            since = "0.2.55",
359
            note = "Use the `mach2` crate instead",
360
        )]
361
        #[allow(deprecated)]
362
        pub type $id = $ty;
363
    };
364
    ($(pub type $id:ident = $ty:ty;)*) => {
365
        $(
366
            deprecated_mach!(
367
                pub type $id = $ty;
368
            );
369
        )*
370
    }
371
}
372
373
#[cfg(test)]
374
mod tests {
375
    use crate::types::CEnumRepr;
376
377
    #[test]
378
    fn c_enumbasic() {
379
        // By default, variants get sequential values.
380
        c_enum! {
381
            pub enum e {
382
                VAR0,
383
                VAR1,
384
                VAR2,
385
            }
386
        }
387
388
        assert_eq!(VAR0, 0 as CEnumRepr);
389
        assert_eq!(VAR1, 1 as CEnumRepr);
390
        assert_eq!(VAR2, 2 as CEnumRepr);
391
    }
392
393
    #[test]
394
    fn c_enumrepr() {
395
        // By default, variants get sequential values.
396
        c_enum! {
397
            #[repr(u16)]
398
            pub enum e {
399
                VAR0,
400
            }
401
        }
402
403
        assert_eq!(VAR0, 0_u16);
404
    }
405
406
    #[test]
407
    fn c_enumset_value() {
408
        // Setting an explicit value resets the count.
409
        c_enum! {
410
            pub enum e {
411
                VAR2 = 2,
412
                VAR3,
413
                VAR4,
414
            }
415
        }
416
417
        assert_eq!(VAR2, 2 as CEnumRepr);
418
        assert_eq!(VAR3, 3 as CEnumRepr);
419
        assert_eq!(VAR4, 4 as CEnumRepr);
420
    }
421
422
    #[test]
423
    fn c_enummultiple_set_value() {
424
        // C enums always take one more than the previous value, unless set to a specific
425
        // value. Duplicates are allowed.
426
        c_enum! {
427
            pub enum e {
428
                VAR0,
429
                VAR2_0 = 2,
430
                VAR3_0,
431
                VAR4_0,
432
                VAR2_1 = 2,
433
                VAR3_1,
434
                VAR4_1,
435
            }
436
        }
437
438
        assert_eq!(VAR0, 0 as CEnumRepr);
439
        assert_eq!(VAR2_0, 2 as CEnumRepr);
440
        assert_eq!(VAR3_0, 3 as CEnumRepr);
441
        assert_eq!(VAR4_0, 4 as CEnumRepr);
442
        assert_eq!(VAR2_1, 2 as CEnumRepr);
443
        assert_eq!(VAR3_1, 3 as CEnumRepr);
444
        assert_eq!(VAR4_1, 4 as CEnumRepr);
445
    }
446
}