Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BitFlags trait #220

Merged
merged 8 commits into from Oct 23, 2021
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
46 changes: 46 additions & 0 deletions src/bitflags_trait.rs
@@ -0,0 +1,46 @@
use core as _core;
Copy link
Contributor

@konsumlamm konsumlamm Aug 4, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
use core as _core;

This is only necessary for use in macros, so that types get resolved correctly. For the definition of the trait, you can just write Option etc.


pub trait BitFlags {
Comment on lines +2 to +3
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
pub trait BitFlags {
/// A trait that is automatically implemented for all bitflags.
pub trait BitFlags {

type Bits;
/// Returns an empty set of flags.
fn empty() -> Self;
/// Returns the set containing all flags.
fn all() -> Self;
/// Returns the raw value of the flags currently stored.
fn bits(&self) -> Self::Bits;
/// Convert from underlying bit representation, unless that
/// representation contains bits that do not correspond to a flag.
fn from_bits(bits: Self::Bits) -> _core::option::Option<Self>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
fn from_bits(bits: Self::Bits) -> _core::option::Option<Self>
fn from_bits(bits: Self::Bits) -> Option<Self>

where Self: Sized;
/// Convert from underlying bit representation, dropping any bits
/// that do not correspond to flags.
fn from_bits_truncate(bits: Self::Bits) -> Self;
/// Convert from underlying bit representation, preserving all
/// bits (even those not corresponding to a defined flag).
///
/// # Safety
///
/// The caller of the `bitflags!` macro can chose to allow or
/// disallow extra bits for their bitflags type.
///
/// The caller of `from_bits_unchecked()` has to ensure that
/// all bits correspond to a defined flag or that extra bits
/// are valid for this bitflags type.
unsafe fn from_bits_unchecked(bits: Self::Bits) -> Self;
/// Returns `true` if no flags are currently stored.
fn is_empty(&self) -> bool;
/// Returns `true` if all flags are currently set.
fn is_all(&self) -> bool;
/// Returns `true` if there are flags common to both `self` and `other`.
fn intersects(&self, other: Self) -> bool;
/// Returns `true` all of the flags in `other` are contained within `self`.
fn contains(&self, other: Self) -> bool;
/// Inserts the specified flags in-place.
fn insert(&mut self, other: Self);
/// Removes the specified flags in-place.
fn remove(&mut self, other: Self);
/// Toggles the specified flags in-place.
fn toggle(&mut self, other: Self);
/// Inserts or removes the specified flags depending on the passed value.
fn set(&mut self, other: Self, value: bool);
}
69 changes: 67 additions & 2 deletions src/lib.rs
Expand Up @@ -261,7 +261,12 @@ extern crate std;
#[doc(hidden)]
pub extern crate core as _core;

/// The macro used to generate the flag structures.
#[doc(inline)]
pub use bitflags_trait::BitFlags;

mod bitflags_trait;

/// The macro used to generate the flag structure.
///
/// See the [crate level docs](../bitflags/index.html) for complete documentation.
///
Expand Down Expand Up @@ -863,6 +868,66 @@ macro_rules! __impl_bitflags {
result
}
}

impl $crate::BitFlags for $BitFlags {
type Bits = $T;

fn empty() -> Self {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You probably want to put inline on most methods here, to enable cross-crate inlining if called via a trait.

$BitFlags::empty()
}

fn all() -> Self {
$BitFlags::all()
}

fn bits(&self) -> $T {
$BitFlags::bits(self)
}

fn from_bits(bits: $T) -> $crate::_core::option::Option<$BitFlags> {
$BitFlags::from_bits(bits)
}

fn from_bits_truncate(bits: $T) -> $BitFlags {
$BitFlags::from_bits_truncate(bits)
}

unsafe fn from_bits_unchecked(bits: $T) -> $BitFlags {
$BitFlags::from_bits_unchecked(bits)
}

fn is_empty(&self) -> bool {
$BitFlags::is_empty(self)
}

fn is_all(&self) -> bool {
$BitFlags::is_all(self)
}

fn intersects(&self, other: $BitFlags) -> bool {
$BitFlags::intersects(self, other)
}

fn contains(&self, other: $BitFlags) -> bool {
$BitFlags::contains(self, other)
}

fn insert(&mut self, other: $BitFlags) {
$BitFlags::insert(self, other)
}

fn remove(&mut self, other: $BitFlags) {
$BitFlags::remove(self, other)
}

fn toggle(&mut self, other: $BitFlags) {
$BitFlags::toggle(self, other)
}

fn set(&mut self, other: $BitFlags, value: bool) {
$BitFlags::set(self, other, value)
}
}
};

// Every attribute that the user writes on a const is applied to the
Expand Down Expand Up @@ -1097,7 +1162,7 @@ mod tests {
unsafe { Flags::from_bits_unchecked(0b1001) },
(extra | Flags::A)
);

let extra = unsafe { EmptyFlags::from_bits_unchecked(0b1000) };
assert_eq!(
unsafe { EmptyFlags::from_bits_unchecked(0b1000) },
Expand Down