Skip to content

Commit

Permalink
more docs
Browse files Browse the repository at this point in the history
  • Loading branch information
KodrAus committed Jul 31, 2023
1 parent 63d4044 commit ac67dea
Show file tree
Hide file tree
Showing 6 changed files with 142 additions and 61 deletions.
4 changes: 3 additions & 1 deletion src/external/arbitrary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

use crate::Flags;

/// Get a random known flags value.
/**
Generate some arbitrary flags value with only known bits set.
*/
pub fn arbitrary<'a, B: Flags>(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<B>
where
B::Bits: arbitrary::Arbitrary<'a>,
Expand Down
12 changes: 10 additions & 2 deletions src/external/serde.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@ use serde::{
Deserialize, Deserializer, Serialize, Serializer,
};

/// Serialize a set of flags as a human-readable string or their underlying bits.
/**
Serialize a set of flags as a human-readable string or their underlying bits.
Any unknown bits will be retained.
*/
pub fn serialize<B: Flags, S: Serializer>(flags: &B, serializer: S) -> Result<S::Ok, S::Error>
where
B::Bits: WriteHex + Serialize,
Expand All @@ -25,7 +29,11 @@ where
}
}

/// Deserialize a set of flags from a human-readable string or their underlying bits.
/**
Deserialize a set of flags from a human-readable string or their underlying bits.
Any unknown bits will be retained.
*/
pub fn deserialize<'de, B: Flags, D: Deserializer<'de>>(deserializer: D) -> Result<B, D::Error>
where
B::Bits: ParseHex + Deserialize<'de>,
Expand Down
31 changes: 19 additions & 12 deletions src/iter.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
//! Iterating over set flag values.
/*!
Yield the bits of a source flags value in a set of contained flags values.
*/

use crate::{Flag, Flags};

/// An iterator over a set of flags.
///
/// Any bits that don't correspond to a valid flag will be yielded
/// as a final item from the iterator.
/**
An iterator over flags values.
This iterator will yield flags values for contained, defined flags first, with any remaining bits yielded
as a final flags value.
*/
pub struct Iter<B: 'static> {
inner: IterNames<B>,
done: bool,
}

impl<B: Flags> Iter<B> {
/// Create a new iterator over the given set of flags.
pub(crate) fn new(flags: &B) -> Self {
Iter {
inner: IterNames::new(flags),
Expand All @@ -22,6 +25,7 @@ impl<B: Flags> Iter<B> {
}

impl<B: 'static> Iter<B> {
// Used by the `bitflags` macro
#[doc(hidden)]
pub const fn __private_const_new(flags: &'static [Flag<B>], source: B, remaining: B) -> Self {
Iter {
Expand Down Expand Up @@ -54,9 +58,12 @@ impl<B: Flags> Iterator for Iter<B> {
}
}

/// An iterator over a set of flags and their names.
///
/// Any bits that don't correspond to a valid flag will be ignored.
/**
An iterator over flags values.
This iterator only yields flags values for contained, defined, named flags. Any remaining bits
won't be yielded, but can be found with the [`IterNames::remaining`] method.
*/
pub struct IterNames<B: 'static> {
flags: &'static [Flag<B>],
idx: usize,
Expand All @@ -65,7 +72,6 @@ pub struct IterNames<B: 'static> {
}

impl<B: Flags> IterNames<B> {
/// Create a new iterator over the given set of flags.
pub(crate) fn new(flags: &B) -> Self {
IterNames {
flags: B::FLAGS,
Expand All @@ -77,6 +83,7 @@ impl<B: Flags> IterNames<B> {
}

impl<B: 'static> IterNames<B> {
// Used by the bitflags macro
#[doc(hidden)]
pub const fn __private_const_new(flags: &'static [Flag<B>], source: B, remaining: B) -> Self {
IterNames {
Expand All @@ -87,11 +94,11 @@ impl<B: 'static> IterNames<B> {
}
}

/// Get the remaining (unyielded) flags.
/// Get a flags value of any remaining bits that haven't been yielded yet.
///
/// Once the iterator has finished, this method can be used to
/// check whether or not there are any bits that didn't correspond
/// to a valid flag remaining.
/// to a contained, defined, named flag remaining.
pub fn remaining(&self) -> &B {
&self.remaining
}
Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ unset unknown bits.
If you're using `bitflags` for flags types defined externally, such as from C, you probably want all
bits to be considered known, in case that external source changes. You can do this using an unnamed
flag, as described in [unnamed flags](#unnamed-flags).
flag, as described in [externally defined flags](#externally-defined-flags).
## Zero-bit flags
Expand Down
84 changes: 48 additions & 36 deletions src/parser.rs
Original file line number Diff line number Diff line change
@@ -1,41 +1,44 @@
//! Parsing flags from text.
//!
//! `bitflags` defines the following *whitespace-insensitive*, *case-sensitive* grammar for flags formatted
//! as text:
//!
//! - _Flags:_ (_Flag_)`|`*
//! - _Flag:_ _Identifier_ | _HexNumber_
//! - _Identifier:_ Any Rust identifier
//! - _HexNumber_: `0x`([0-9a-fA-F])*
//!
//! As an example, this is how `Flags::A | Flags::B | 0x0c` can be represented as text:
//!
//! ```text
//! A | B | 0x0c
//! ```
//!
//! Alternatively, it could be represented without whitespace:
//!
//! ```text
//! A|B|0x0C
//! ```
//!
//! Note that identifiers are *case-sensitive*, so the following is *not equivalent*:
//!
//! ```text
//! a | b | 0x0c
//! ```
/*!
Parsing flags from text.
Format and parse a flags value as text using the following grammar:
- _Flags:_ (_Whitespace_ _Flag_ _Whitespace_)`|`*
- _Flag:_ _Name_ | _Hex Number_
- _Name:_ The name of any defined flag
- _Hex Number_: `0x`([0-9a-fA-F])*
- _Whitespace_: (\s)*
As an example, this is how `Flags::A | Flags::B | 0x0c` can be represented as text:
```text
A | B | 0x0c
```
Alternatively, it could be represented without whitespace:
```text
A|B|0x0C
```
Note that identifiers are *case-sensitive*, so the following is *not equivalent*:
```text
a|b|0x0C
```
*/

#![allow(clippy::let_unit_value)]

use core::fmt::{self, Write};

use crate::{Bits, Flags};

/// Write a set of flags to a writer.
///
/// Any bits that don't correspond to a valid flag will be formatted
/// as a hex number.
/**
Write a flags value as text.
Any bits that aren't part of a contained flag will be formatted as a hex number.
*/
pub fn to_writer<B: Flags>(flags: &B, mut writer: impl Write) -> Result<(), fmt::Error>
where
B::Bits: WriteHex,
Expand Down Expand Up @@ -85,9 +88,12 @@ where
}
}

/// Parse a set of flags from text.
///
/// This function will fail on unknown flags rather than ignore them.
/**
Parse a flags value from text.
This function will fail on any names that don't correspond to defined flags.
Unknown bits will be retained.
*/
pub fn from_str<B: Flags>(input: &str) -> Result<B, ParseError>
where
B::Bits: ParseHex,
Expand Down Expand Up @@ -128,13 +134,19 @@ where
Ok(parsed_flags)
}

/// Encode a value as a hex number.
/**
Encode a value as a hex string.
Implementors of this trait should not write the leading `0x` prefix.
*/
pub trait WriteHex {
/// Write the value as hex.
fn write_hex<W: fmt::Write>(&self, writer: W) -> fmt::Result;
}

/// Parse a value from a number encoded as a hex string.
/**
Parse a value from a hex string.
*/
pub trait ParseHex {
/// Parse the value from hex.
fn parse_hex(input: &str) -> Result<Self, ParseError>
Expand Down
70 changes: 61 additions & 9 deletions src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,31 +8,57 @@ use crate::{
parser::{ParseError, ParseHex, WriteHex},
};

/// A set of bits in a bits type that may have a unique name.
/**
A defined flags value that may be named or unnamed.
*/
pub struct Flag<B> {
name: &'static str,
value: B,
}

impl<B> Flag<B> {
/// Create a new flag with the given name and value.
///
/// If `name` is empty then the flag is unnamed.
/**
Define a flag.
If `name` is non-empty then the flag is named, otherwise it's unnamed.
*/
pub const fn new(name: &'static str, value: B) -> Self {
Flag { name, value }
}

/// Get the name of this flag.
///
/// If `name` is empty then the flag is unnamed.
/**
Get the name of this flag.
If the flag is unnamed then the returned string will be empty.
*/
pub const fn name(&self) -> &'static str {
self.name
}

/// Get the value of this flag.
/**
Get the flags value of this flag.
*/
pub const fn value(&self) -> &B {
&self.value
}

/**
Whether the flag is named.
If [`name`] returns a non-empty string then this method will return `true`.
*/
pub const fn is_named(&self) -> bool {
self.name != ""
}

/**
Whether the flag is unnamed.
If [`name`] returns a non-empty string then this method will return `false`.
*/
pub const fn is_unnamed(&self) -> bool {
self.name == ""
}
}

/**
Expand Down Expand Up @@ -77,6 +103,30 @@ impl Flags for MyFlags {
}
}
```
## Using `Flags`
The `Flags` trait can be used generically to work with any flags types. In this example,
we can count the number of defined named flags:
```
# use bitflags::{bitflags, Flags};
fn defined_flags<F: Flags>() -> usize {
F::FLAGS.iter().filter(|f| f.is_named()).count()
}
bitflags! {
struct MyFlags: u8 {
const A = 1;
const B = 1 << 1;
const C = 1 << 2;
const _ = !0;
}
}
assert_eq!(3, defined_flags::<MyFlags>());
```
*/
pub trait Flags: Sized + 'static {
/// The set of defined flags.
Expand Down Expand Up @@ -263,7 +313,9 @@ pub trait Flags: Sized + 'static {
}
}

/// Underlying storage for a flags type.
/**
A bits type that can be used as storage for a flags type.
*/
pub trait Bits:
Clone
+ Copy
Expand Down

0 comments on commit ac67dea

Please sign in to comment.