Skip to content

Commit

Permalink
Merge pull request #282 from KodrAus/feat/internal-flags-types
Browse files Browse the repository at this point in the history
Split generated code into two types
  • Loading branch information
KodrAus committed Aug 22, 2022
2 parents 810dc35 + c5b2ff0 commit 07af9c4
Show file tree
Hide file tree
Showing 31 changed files with 1,148 additions and 570 deletions.
13 changes: 11 additions & 2 deletions .github/workflows/rust.yml
Expand Up @@ -46,8 +46,17 @@ jobs:
profile: minimal
toolchain: ${{ matrix.channel }}-${{ matrix.rust_target }}

- name: Tests
run: cargo test --features example_generated
- name: Install cargo-hack
run: cargo install cargo-hack

- name: Powerset
run: cargo hack test --feature-powerset --lib --optional-deps "serde" --depth 3 --skip rustc-dep-of-std

- name: Docs
run: cargo doc --features example_generated

- name: Smoke test
run: cargo run --manifest-path tests/smoke-test/Cargo.toml

embedded:
name: Build (embedded)
Expand Down
8 changes: 4 additions & 4 deletions Cargo.toml
Expand Up @@ -16,16 +16,16 @@ categories = ["no-std"]
description = """
A macro to generate structures which behave like bitflags.
"""
exclude = ["bors.toml"]
exclude = ["tests", ".github"]

[dependencies]
core = { version = '1.0.0', optional = true, package = 'rustc-std-workspace-core' }
compiler_builtins = { version = '0.1.2', optional = true }
serde = { version = "1.0", optional = true }
core = { version = "1.0.0", optional = true, package = "rustc-std-workspace-core" }
compiler_builtins = { version = "0.1.2", optional = true }

[dev-dependencies]
trybuild = "1.0"
rustversion = "1.0"
serde = "1.0"
serde_derive = "1.0"
serde_json = "1.0"

Expand Down
35 changes: 22 additions & 13 deletions src/bitflags_trait.rs
@@ -1,8 +1,5 @@
use core::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Not};

#[doc(hidden)]
pub trait ImplementedByBitFlagsMacro {}

/// A trait that is automatically implemented for all bitflags.
///
/// It should not be implemented manually.
Expand All @@ -25,16 +22,7 @@ pub trait BitFlags: ImplementedByBitFlagsMacro {
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;
fn from_bits_retain(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.
Expand All @@ -53,9 +41,22 @@ pub trait BitFlags: ImplementedByBitFlagsMacro {
fn set(&mut self, other: Self, value: bool);
}

/// A marker trait that signals that an implementation of `BitFlags` came from the `bitflags!` macro.
///
/// There's nothing stopping an end-user from implementing this trait, but we don't guarantee their
/// manual implementations won't break between non-breaking releases.
#[doc(hidden)]
pub trait ImplementedByBitFlagsMacro {}

// Not re-exported
pub trait Sealed {}

// Private implementation details
//
// The `Bits`, `PublicFlags`, and `InternalFlags` traits are implementation details of the `bitflags!`
// macro that we're free to change here. They work with the `bitflags!` macro to separate the generated
// code that belongs to end-users, and the generated code that belongs to this library.

/// A private trait that encodes the requirements of underlying bits types that can hold flags.
///
/// This trait may be made public at some future point, but it presents a compatibility hazard
Expand Down Expand Up @@ -107,3 +108,11 @@ impl_bits! {
u64, i64,
u128, i128,
}

pub trait PublicFlags {
type InternalFlags;
}

pub trait InternalFlags {
type PublicFlags;
}
31 changes: 30 additions & 1 deletion src/example_generated.rs
Expand Up @@ -9,6 +9,35 @@ bitflags! {
const A = 0b00000001;
const B = 0b00000010;
const C = 0b00000100;
const ABC = Self::A.bits | Self::B.bits | Self::C.bits;
const ABC = Self::A.bits() | Self::B.bits() | Self::C.bits();
}
}

/// This is the same internal field available as `self.0` on bitflags types.
/// These types aren't reachable by callers of `bitflags!`, they don't appear in the API of your
/// crate, but you can still interact with them through `self.0` in the module that defines the
/// bitflags type.
///
/// You can use this example as a reference for what methods are available to all internal bitflags
/// fields if you want to add custom functionality to your bitflags types.
///
/// Note that this struct is just for documentation purposes only, it must not be used outside
/// this crate.
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(transparent)]
pub struct FlagsField {
bits: u32,
}

__impl_internal_bitflags! {
FlagsField: u32 {
A;
B;
C;
ABC;
}
}

impl crate::__private::InternalFlags for FlagsField {
type PublicFlags = Flags;
}

0 comments on commit 07af9c4

Please sign in to comment.