331 lines
7.9 KiB
Rust
331 lines
7.9 KiB
Rust
// Thanks to Tokio for this macro
|
|
macro_rules! feature {
|
|
(
|
|
#![$meta:meta]
|
|
$($item:item)*
|
|
) => {
|
|
$(
|
|
#[cfg($meta)]
|
|
#[cfg_attr(docsrs, doc(cfg($meta)))]
|
|
$item
|
|
)*
|
|
}
|
|
}
|
|
|
|
/// The `libc_bitflags!` macro helps with a common use case of defining a public bitflags type
|
|
/// with values from the libc crate. It is used the same way as the `bitflags!` macro, except
|
|
/// that only the name of the flag value has to be given.
|
|
///
|
|
/// The `libc` crate must be in scope with the name `libc`.
|
|
///
|
|
/// # Example
|
|
/// ```ignore
|
|
/// libc_bitflags!{
|
|
/// pub struct ProtFlags: libc::c_int {
|
|
/// PROT_NONE;
|
|
/// PROT_READ;
|
|
/// /// PROT_WRITE enables write protect
|
|
/// PROT_WRITE;
|
|
/// PROT_EXEC;
|
|
/// #[cfg(linux_android)]
|
|
/// PROT_GROWSDOWN;
|
|
/// #[cfg(linux_android)]
|
|
/// PROT_GROWSUP;
|
|
/// }
|
|
/// }
|
|
/// ```
|
|
///
|
|
/// Example with casting, due to a mistake in libc. In this example, the
|
|
/// various flags have different types, so we cast the broken ones to the right
|
|
/// type.
|
|
///
|
|
/// ```ignore
|
|
/// libc_bitflags!{
|
|
/// pub struct SaFlags: libc::c_ulong {
|
|
/// SA_NOCLDSTOP as libc::c_ulong;
|
|
/// SA_NOCLDWAIT;
|
|
/// SA_NODEFER as libc::c_ulong;
|
|
/// SA_ONSTACK;
|
|
/// SA_RESETHAND as libc::c_ulong;
|
|
/// SA_RESTART as libc::c_ulong;
|
|
/// SA_SIGINFO;
|
|
/// }
|
|
/// }
|
|
/// ```
|
|
macro_rules! libc_bitflags {
|
|
(
|
|
$(#[$outer:meta])*
|
|
pub struct $BitFlags:ident: $T:ty {
|
|
$(
|
|
$(#[$inner:ident $($args:tt)*])*
|
|
$Flag:ident $(as $cast:ty)*;
|
|
)+
|
|
}
|
|
) => {
|
|
::bitflags::bitflags! {
|
|
#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
|
|
#[repr(transparent)]
|
|
$(#[$outer])*
|
|
pub struct $BitFlags: $T {
|
|
$(
|
|
$(#[$inner $($args)*])*
|
|
const $Flag = libc::$Flag $(as $cast)*;
|
|
)+
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
/// The `libc_enum!` macro helps with a common use case of defining an enum exclusively using
|
|
/// values from the `libc` crate. This macro supports both `pub` and private `enum`s.
|
|
///
|
|
/// The `libc` crate must be in scope with the name `libc`.
|
|
///
|
|
/// # Example
|
|
/// ```ignore
|
|
/// libc_enum!{
|
|
/// pub enum ProtFlags {
|
|
/// PROT_NONE,
|
|
/// PROT_READ,
|
|
/// PROT_WRITE,
|
|
/// PROT_EXEC,
|
|
/// #[cfg(linux_android)]
|
|
/// PROT_GROWSDOWN,
|
|
/// #[cfg(linux_android)]
|
|
/// PROT_GROWSUP,
|
|
/// }
|
|
/// }
|
|
/// ```
|
|
// Some targets don't use all rules.
|
|
#[allow(unused_macro_rules)]
|
|
macro_rules! libc_enum {
|
|
// Exit rule.
|
|
(@make_enum
|
|
name: $BitFlags:ident,
|
|
{
|
|
$v:vis
|
|
attrs: [$($attrs:tt)*],
|
|
entries: [$($entries:tt)*],
|
|
}
|
|
) => {
|
|
$($attrs)*
|
|
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
|
|
$v enum $BitFlags {
|
|
$($entries)*
|
|
}
|
|
};
|
|
|
|
// Exit rule including TryFrom
|
|
(@make_enum
|
|
name: $BitFlags:ident,
|
|
{
|
|
$v:vis
|
|
attrs: [$($attrs:tt)*],
|
|
entries: [$($entries:tt)*],
|
|
from_type: $repr:path,
|
|
try_froms: [$($try_froms:tt)*]
|
|
}
|
|
) => {
|
|
$($attrs)*
|
|
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
|
|
$v enum $BitFlags {
|
|
$($entries)*
|
|
}
|
|
impl ::std::convert::TryFrom<$repr> for $BitFlags {
|
|
type Error = $crate::Error;
|
|
#[allow(unused_doc_comments)]
|
|
#[allow(deprecated)]
|
|
#[allow(unused_attributes)]
|
|
fn try_from(x: $repr) -> $crate::Result<Self> {
|
|
match x {
|
|
$($try_froms)*
|
|
_ => Err($crate::Error::EINVAL)
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
// Done accumulating.
|
|
(@accumulate_entries
|
|
name: $BitFlags:ident,
|
|
{
|
|
$v:vis
|
|
attrs: $attrs:tt,
|
|
},
|
|
$entries:tt,
|
|
$try_froms:tt;
|
|
) => {
|
|
libc_enum! {
|
|
@make_enum
|
|
name: $BitFlags,
|
|
{
|
|
$v
|
|
attrs: $attrs,
|
|
entries: $entries,
|
|
}
|
|
}
|
|
};
|
|
|
|
// Done accumulating and want TryFrom
|
|
(@accumulate_entries
|
|
name: $BitFlags:ident,
|
|
{
|
|
$v:vis
|
|
attrs: $attrs:tt,
|
|
from_type: $repr:path,
|
|
},
|
|
$entries:tt,
|
|
$try_froms:tt;
|
|
) => {
|
|
libc_enum! {
|
|
@make_enum
|
|
name: $BitFlags,
|
|
{
|
|
$v
|
|
attrs: $attrs,
|
|
entries: $entries,
|
|
from_type: $repr,
|
|
try_froms: $try_froms
|
|
}
|
|
}
|
|
};
|
|
|
|
// Munch an attr.
|
|
(@accumulate_entries
|
|
name: $BitFlags:ident,
|
|
$prefix:tt,
|
|
[$($entries:tt)*],
|
|
[$($try_froms:tt)*];
|
|
#[$attr:meta] $($tail:tt)*
|
|
) => {
|
|
libc_enum! {
|
|
@accumulate_entries
|
|
name: $BitFlags,
|
|
$prefix,
|
|
[
|
|
$($entries)*
|
|
#[$attr]
|
|
],
|
|
[
|
|
$($try_froms)*
|
|
#[$attr]
|
|
];
|
|
$($tail)*
|
|
}
|
|
};
|
|
|
|
// Munch last ident if not followed by a comma.
|
|
(@accumulate_entries
|
|
name: $BitFlags:ident,
|
|
$prefix:tt,
|
|
[$($entries:tt)*],
|
|
[$($try_froms:tt)*];
|
|
$entry:ident
|
|
) => {
|
|
libc_enum! {
|
|
@accumulate_entries
|
|
name: $BitFlags,
|
|
$prefix,
|
|
[
|
|
$($entries)*
|
|
$entry = libc::$entry,
|
|
],
|
|
[
|
|
$($try_froms)*
|
|
libc::$entry => Ok($BitFlags::$entry),
|
|
];
|
|
}
|
|
};
|
|
|
|
// Munch an ident; covers terminating comma case.
|
|
(@accumulate_entries
|
|
name: $BitFlags:ident,
|
|
$prefix:tt,
|
|
[$($entries:tt)*],
|
|
[$($try_froms:tt)*];
|
|
$entry:ident,
|
|
$($tail:tt)*
|
|
) => {
|
|
libc_enum! {
|
|
@accumulate_entries
|
|
name: $BitFlags,
|
|
$prefix,
|
|
[
|
|
$($entries)*
|
|
$entry = libc::$entry,
|
|
],
|
|
[
|
|
$($try_froms)*
|
|
libc::$entry => Ok($BitFlags::$entry),
|
|
];
|
|
$($tail)*
|
|
}
|
|
};
|
|
|
|
// Munch an ident and cast it to the given type; covers terminating comma.
|
|
(@accumulate_entries
|
|
name: $BitFlags:ident,
|
|
$prefix:tt,
|
|
[$($entries:tt)*],
|
|
[$($try_froms:tt)*];
|
|
$entry:ident as $ty:ty,
|
|
$($tail:tt)*
|
|
) => {
|
|
libc_enum! {
|
|
@accumulate_entries
|
|
name: $BitFlags,
|
|
$prefix,
|
|
[
|
|
$($entries)*
|
|
$entry = libc::$entry as $ty,
|
|
],
|
|
[
|
|
$($try_froms)*
|
|
libc::$entry as $ty => Ok($BitFlags::$entry),
|
|
];
|
|
$($tail)*
|
|
}
|
|
};
|
|
|
|
// Entry rule.
|
|
(
|
|
$(#[$attr:meta])*
|
|
$v:vis enum $BitFlags:ident {
|
|
$($vals:tt)*
|
|
}
|
|
) => {
|
|
libc_enum! {
|
|
@accumulate_entries
|
|
name: $BitFlags,
|
|
{
|
|
$v
|
|
attrs: [$(#[$attr])*],
|
|
},
|
|
[],
|
|
[];
|
|
$($vals)*
|
|
}
|
|
};
|
|
|
|
// Entry rule including TryFrom
|
|
(
|
|
$(#[$attr:meta])*
|
|
$v:vis enum $BitFlags:ident {
|
|
$($vals:tt)*
|
|
}
|
|
impl TryFrom<$repr:path>
|
|
) => {
|
|
libc_enum! {
|
|
@accumulate_entries
|
|
name: $BitFlags,
|
|
{
|
|
$v
|
|
attrs: [$(#[$attr])*],
|
|
from_type: $repr,
|
|
},
|
|
[],
|
|
[];
|
|
$($vals)*
|
|
}
|
|
};
|
|
}
|