pub struct FlagsBuilder { /* private fields */ }Expand description
§(Bit)Flag/Enum Builder.
FlagsBuilder is a compile-time (build.rs) tool for generating
small (single-byte) bitflag enums, with every flag — and combination
— explicitly defined as its own unique variant.
It supports 1..=8 primary flags, zero, and a couple hundred combinations
(that argyle will figure out for you).
The resulting code contains no unsafe blocks, no dependencies (other than
std), and no runtime performance penalties, just the warmth and
reassurance of a strictly-bound type.
§Examples
As the name suggests, FlagsBuilder employs builder-style configuration
methods, allowing indefinite chaining, start to finish.
§build.rs
use argyle::FlagsBuilder;
FlagsBuilder::new("MyFlags") // Name of enum.
.with_docs("# My Flags Are Awesome!") // Enum docs.
.public() // Make it pub instead of pub(crate).
.with_flag("FlagOne", None) // A primary flag.
.with_flag("FlagTwo", Some("# Second Flag")) // A primary flag with docs.
.with_alias("Both", ["FlagOne", "FlagTwo"], None) // A named combo.
.with_defaults(["FlagOne", "FlagTwo"]) // MyFlags::default() == MyFlags::Both
.save(std::env::var("OUT_DIR").unwrap().join("flags.rs")); // Save it!§lib.rs
To use it, just import the build artifact into your library like:
// Generated by build.rs.
include!(concat!(env!("OUT_DIR"), "/flags.rs"));
// The type is "yours"; expand as needed!
impl From<MyFlags> for u8 {
#[inline]
fn from(src: MyFlags) -> Self { src as Self }
}§Generated Structure.
Custom enums generated by FlagsBuilder implement the various
bit-related traits —
BitAnd/BitAndAssign,
BitOr/BitOrAssign, and
BitXor/BitXorAssign —
so can be worked with in the usual manner.
A few additional helpers like contains and some basic unit tests are
provided as well.
All told, you’ll wind up with something like this:
#[repr(u8)]
#[derive(Debug, Clone, Copy, Default, Eq, PartialEq)]
/// # My Awesome Enum.
pub(crate) enum AwesomeEnum {
#[default]
None = 0b0000_u8, // Zero is always called "None".
A = 0b0001_u8,
B = 0b0010_u8,
C = 0b0100_u8,
D = 0b1000_u8,
// …
Z = 0b1111_u8,
}
impl AwesomeEnum {
/// # (Primary) Flags.
pub(crate) const FLAGS: [Self; 4] = [
Self::A, Self::B, Self::C, Self::D,
];
#[must_use]
/// # From `u8`.
///
/// Find and return the flag corresponding to the `u8`. If out of range,
/// `Self::None` is returned.
pub(crate) const fn from_u8(num: u8) -> Self {
// …
}
}
impl AwesomeEnum {
#[must_use]
/// # Contains Flag?
///
/// Returns `true` if `self` is or comprises `other`, `false` if not.
pub(crate) const fn contains(self, other: Self) -> bool {
// …
}
#[must_use]
/// # Contains Any Part of Flag?
///
/// Returns the bits common to `self` and `other`, if any.
pub(crate) const fn contains_any(self, other: Self) -> Option<Self> {
// …
}
#[must_use]
/// # Is None?
///
/// Returns `true` if [`AwesomeEnum::None`], meaning no bits are set.
pub(crate) const fn is_none(self) -> bool {
// …
}
/// # Set Flag Bits.
///
/// Add any missing bits from `other` to `self`.
///
/// This is equivalent to `self |= other`, but constant.
pub(crate) const fn set(&mut self, other: Self) {
// …
}
/// # Remove Flag Bits.
///
/// Strip `other`'s bits from `self`.
///
/// This is equivalent to `self &= ! other`, but constant.
pub(crate) const fn unset(&mut self, other: Self) {
// …
}
#[must_use]
/// # With Flag Bits.
///
/// Return the combination of `self` and `other`.
///
/// This is equivalent to `self | other`, but constant.
pub(crate) const fn with(self, other: Self) -> Self {
// …
}
#[must_use]
/// # Without Flag Bits.
///
/// Remove `other` from `self`, returning the difference.
///
/// This is equivalent to `self & ! other`, but constant.
pub(crate) const fn without(self, other: Self) -> Self {
// …
}
}If you’re having trouble visualizing it, clone the repository and check out
the flags_builder example.
Implementations§
Source§impl FlagsBuilder
impl FlagsBuilder
Sourcepub fn new<S: AsRef<str>>(name: S) -> Self
pub fn new<S: AsRef<str>>(name: S) -> Self
§New Instance.
Initialize a new builder for a custom enum named name.
As with flag/alias names, the enum name must be ASCII alphanumeric (alpha first), and PascalCase.
§Examples
use argyle::FlagsBuilder;
// Start a builder called Settings.
let mut builder = FlagsBuilder::new("Settings");§Panics
This method will panic if the name is invalid.
Sourcepub fn with_docs<S: AsRef<str>>(self, docs: S) -> Self
pub fn with_docs<S: AsRef<str>>(self, docs: S) -> Self
§With Documentation.
Customize the documentation that will wind up being attached to the enum definition.
§Examples
use argyle::FlagsBuilder;
FlagsBuilder::new("Settings")
.with_docs("# App Settings
This enum holds the various boolean…");Long write-ups can quickly get untidy with all the line breaks and whatnot. Storing the docs externally can be useful:
use argyle::FlagsBuilder;
FlagsBuilder::new("Settings")
.with_docs(include_str!("../skel/settings.txt"));Sourcepub fn with_defaults<S, I>(self, flags: I) -> Self
pub fn with_defaults<S, I>(self, flags: I) -> Self
§With Default(s).
By default, the Default implementation for custom enums is None.
If you’d rather it start with one or more flags flipped on, use this method to specify them.
If you’d rather default to everything, use
FlagsBuilder::with_default_all instead.
§Examples
use argyle::FlagsBuilder;
FlagsBuilder::new("Fruit")
.with_flag("Apples", None)
.with_flag("Bananas", None)
.with_flag("Carrots", None)
.with_flag("Dates", None)
.with_defaults(["Apples", "Bananas", "Carrots"]);§Panics
This method doesn’t check that the flags have been defined — that happens during save — but will panic if the names are invalid.
Sourcepub const fn with_default_all(self) -> Self
pub const fn with_default_all(self) -> Self
§Default Everything!
By default, the Default implementation for custom enums is None.
Use this method to have it return all the bits (every flag) instead.
If you’d rather the default fall somewhere between the extremes, use
FlagsBuilder::with_defaults instead.
§Examples
use argyle::FlagsBuilder;
FlagsBuilder::new("Fruit")
.with_flag("Apples", None)
.with_flag("Bananas", None)
.with_flag("Carrots", None)
.with_flag("Dates", None)
.with_default_all();Source§impl FlagsBuilder
§Primary Flags.
impl FlagsBuilder
§Primary Flags.
Sourcepub fn with_flag<S: AsRef<str>>(self, name: S, docs: Option<S>) -> Self
pub fn with_flag<S: AsRef<str>>(self, name: S, docs: Option<S>) -> Self
§With Flag.
Use this method to define a new primary flag with the given variant name and (optional) documentation.
As with the enum itself, names must be ASCII alphanumeric (alpha first), and PascalCase.
A given enum can have anywhere from 1..=8 primary flags.
§Examples
use argyle::FlagsBuilder;
FlagsBuilder::new("Animals")
.with_flag("BullFrog", None);§Panics
This method will panic if the flag name is invalid or has already been defined.
Sourcepub fn with_complex_flag<S, I>(self, name: S, flags: I, docs: Option<S>) -> Self
pub fn with_complex_flag<S, I>(self, name: S, flags: I, docs: Option<S>) -> Self
§With Complex Flag.
Like FlagsBuilder::with_flag, but for a flag that implies other
flag(s), inheriting their bits (along with its own).
Implied flag names passed to this method must correspond to flags; aliases are not allowed.
§Examples
use argyle::FlagsBuilder;
FlagsBuilder::new("Animals")
.with_flag("BullFrog", None) // 0b0001
.with_flag("Bat", None) // 0b0010
.with_complex_flag("Frog", ["BullFrog"], None) // 0b0101
.with_alias("All", ["Bat", "Frog"], None); // 0b0111§Panics
This method will panic if any of the flag names are invalid, or the main name has already been defined.
Sourcepub fn with_alias<S, I>(self, name: S, flags: I, docs: Option<S>) -> Self
pub fn with_alias<S, I>(self, name: S, flags: I, docs: Option<S>) -> Self
§With Alias.
Combinative aliases — the “AB” in A | B == AB — are automatically
generated by FlagsBuilder, but can be selectively named if any of
them hold special meaning for you.
As with the enum and primary flags, alias names must be ASCII alphanumeric (alpha first), and PascalCase.
§Examples
use argyle::FlagsBuilder;
FlagsBuilder::new("Compression")
.with_flag("FmtAvif", None)
.with_flag("FmtJpeg", None)
.with_flag("FmtJxl", None)
.with_flag("FmtPng", None)
.with_flag("FmtWebP", None)
.with_alias("FmtOld", ["FmtJpeg", "FmtPng"], None)
.with_alias("FmtNew", ["FmtAvif", "FmtJxl", "FmtWebP"], None);§Panics
This method will panic if the alias or flag names are invalid, if the alias has already been defined (including as a flag), or if it references fewer than two flags.
Source§impl FlagsBuilder
impl FlagsBuilder
Sourcepub fn save<P: AsRef<Path>>(&self, file: P)
pub fn save<P: AsRef<Path>>(&self, file: P)
§Save it to a File!
Generate and save the custom flag enum to the specified file.
Note that many environments prohibit writes to arbitrary locations; for
best results, your path should be somewhere under OUT_DIR.
§Examples
let out_dir: &Path = std::env::var("OUT_DIR").unwrap().as_ref();
flags.save(out_dir.join("flags.rs"));If you’d prefer to handle the saving manually, the code can be
obtained by simply calling FlagsBuilder::to_string instead.
use argyle::FlagsBuilder;
let out = FlagsBuilder::new("Names")
.with_flag("John", None)
.with_flag("Jane", None)
.to_string();§Panics
This method will panic if the write fails for any reason.
Trait Implementations§
Source§impl Clone for FlagsBuilder
impl Clone for FlagsBuilder
Source§fn clone(&self) -> FlagsBuilder
fn clone(&self) -> FlagsBuilder
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more