forked from nix-rust/nix
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
We define many bitflags types with values from the libc crate. Currently these look like this: bitflags!{ flags ProtFlags: libc::c_int { const PROT_NONE = libc::PROT_NONE, const PROT_READ = libc::PROT_READ, const PROT_WRITE = libc::PROT_WRITE, const PROT_EXEC = libc::PROT_EXEC, #[cfg(any(target_os = "linux", target_os = "android"))] const PROT_GROWSDOWN = libc::PROT_GROWSDOWN, #[cfg(any(target_os = "linux", target_os = "android"))] const PROT_GROWSUP = libc::PROT_GROWSUP, } } There's some repetition which is tedious. With the new macro, the above can instead be written libc_bitflags!{ flags ProtFlags: libc::c_int { PROT_NONE, PROT_READ, PROT_WRITE, PROT_EXEC, #[cfg(any(target_os = "linux", target_os = "android"))] PROT_GROWSDOWN, #[cfg(any(target_os = "linux", target_os = "android"))] PROT_GROWSUP, } } Thanks to Daniel Keep for the Little Book of Rust Macros, and for helping with this macro. Refs nix-rust#264
- Loading branch information
1 parent
97157b4
commit b4c9f5b
Showing
3 changed files
with
213 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,188 @@ | ||
/// The `libc_bitflags!` macro helps with a common use case of defining bitflags 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 | ||
/// ``` | ||
/// libc_bitflags!{ | ||
/// flags ProtFlags: libc::c_int { | ||
/// PROT_NONE, | ||
/// PROT_READ, | ||
/// PROT_WRITE, | ||
/// PROT_EXEC, | ||
/// #[cfg(any(target_os = "linux", target_os = "android"))] | ||
/// PROT_GROWSDOWN, | ||
/// #[cfg(any(target_os = "linux", target_os = "android"))] | ||
/// PROT_GROWSUP, | ||
/// } | ||
/// } | ||
/// ``` | ||
macro_rules! libc_bitflags { | ||
// (non-pub) Exit rule. | ||
(@call_bitflags | ||
{ | ||
name: $BitFlags:ident, | ||
type: $T:ty, | ||
attrs: [$($attrs:tt)*], | ||
flags: [$($flags:tt)*], | ||
} | ||
) => { | ||
bitflags! { | ||
$($attrs)* | ||
flags $BitFlags: $T { | ||
$($flags)* | ||
} | ||
} | ||
}; | ||
|
||
// (pub) Exit rule. | ||
(@call_bitflags | ||
{ | ||
pub, | ||
name: $BitFlags:ident, | ||
type: $T:ty, | ||
attrs: [$($attrs:tt)*], | ||
flags: [$($flags:tt)*], | ||
} | ||
) => { | ||
bitflags! { | ||
$($attrs)* | ||
pub flags $BitFlags: $T { | ||
$($flags)* | ||
} | ||
} | ||
}; | ||
|
||
// (non-pub) Done accumulating. | ||
(@accumulate_flags | ||
{ | ||
name: $BitFlags:ident, | ||
type: $T:ty, | ||
attrs: $attrs:tt, | ||
}, | ||
$flags:tt; | ||
) => { | ||
libc_bitflags! { | ||
@call_bitflags | ||
{ | ||
name: $BitFlags, | ||
type: $T, | ||
attrs: $attrs, | ||
flags: $flags, | ||
} | ||
} | ||
}; | ||
|
||
// (pub) Done accumulating. | ||
(@accumulate_flags | ||
{ | ||
pub, | ||
name: $BitFlags:ident, | ||
type: $T:ty, | ||
attrs: $attrs:tt, | ||
}, | ||
$flags:tt; | ||
) => { | ||
libc_bitflags! { | ||
@call_bitflags | ||
{ | ||
pub, | ||
name: $BitFlags, | ||
type: $T, | ||
attrs: $attrs, | ||
flags: $flags, | ||
} | ||
} | ||
}; | ||
|
||
// Munch an attr. | ||
(@accumulate_flags | ||
$prefix:tt, | ||
[$($flags:tt)*]; | ||
#[$attr:meta] $($tail:tt)* | ||
) => { | ||
libc_bitflags! { | ||
@accumulate_flags | ||
$prefix, | ||
[ | ||
$($flags)* | ||
#[$attr] | ||
]; | ||
$($tail)* | ||
} | ||
}; | ||
|
||
// Munch last ident if not followed by a comma. | ||
(@accumulate_flags | ||
$prefix:tt, | ||
[$($flags:tt)*]; | ||
$flag:ident | ||
) => { | ||
libc_bitflags! { | ||
@accumulate_flags | ||
$prefix, | ||
[ | ||
$($flags)* | ||
const $flag = libc::$flag, | ||
]; | ||
} | ||
}; | ||
|
||
// Munch an ident; covers terminating comma case. | ||
(@accumulate_flags | ||
$prefix:tt, | ||
[$($flags:tt)*]; | ||
$flag:ident, $($tail:tt)* | ||
) => { | ||
libc_bitflags! { | ||
@accumulate_flags | ||
$prefix, | ||
[ | ||
$($flags)* | ||
const $flag = libc::$flag, | ||
]; | ||
$($tail)* | ||
} | ||
}; | ||
|
||
// (non-pub) Entry rule. | ||
( | ||
$(#[$attr:meta])* | ||
flags $BitFlags:ident: $T:ty { | ||
$($vals:tt)* | ||
} | ||
) => { | ||
libc_bitflags! { | ||
@accumulate_flags | ||
{ | ||
name: $BitFlags, | ||
type: $T, | ||
attrs: [$(#[$attr])*], | ||
}, | ||
[]; | ||
$($vals)* | ||
} | ||
}; | ||
|
||
// (pub) Entry rule. | ||
( | ||
$(#[$attr:meta])* | ||
pub flags $BitFlags:ident: $T:ty { | ||
$($vals:tt)* | ||
} | ||
) => { | ||
libc_bitflags! { | ||
@accumulate_flags | ||
{ | ||
pub, | ||
name: $BitFlags, | ||
type: $T, | ||
attrs: [$(#[$attr])*], | ||
}, | ||
[]; | ||
$($vals)* | ||
} | ||
}; | ||
} |