use ::core::fmt::Debug;
use ::core::hash::Hash;
use ::core::ops::{
Not,
BitAnd, BitAndAssign,
BitOr, BitOrAssign,
BitXor, BitXorAssign,
Add, AddAssign,
Sub, SubAssign,
Index,
Range,
};
use vexmacro::const_binary_search_fn;
pub trait Flags: 'static
+ Sized
+ Send
+ Sync
+ Debug
+ Copy
+ Eq
+ Ord
+ Hash
+ Not
+ BitAnd<Self, Output = Self>
+ BitAndAssign<Self>
+ BitOr<Self, Output = Self>
+ BitOrAssign<Self>
+ BitXor<Self, Output = Self>
+ BitXorAssign<Self>
+ Add<Self, Output = Self>
+ AddAssign<Self>
+ Sub<Self, Output = Self>
+ SubAssign<Self>
+ Index<u32, Output = bool>
+ Index<usize, Output = bool>
{
type MaskType;
type MasksArrayType;
type BytesArrayType;
const BITS: u32;
const USED_BITS: u32;
const UNUSED_BITS: u32;
const MASK_BITS: u32;
const MASK_SIZE: usize;
const MASK_COUNT: usize;
const SINGLE_FLAG_COUNT: usize;
const GROUP_FLAG_COUNT: usize;
const TOTAL_FLAG_COUNT: usize;
const NONE: Self;
const ALL: Self;
const FLAGS_TABLE: &'static [FlagRow<Self>];
const SINGLE_FLAGS: &'static [FlagRow<Self>];
const GROUP_FLAGS: &'static [FlagRow<Self>];
const BIT_ORDERED_FLAGS_TABLE: &'static [FlagIndex];
const ORDERED_FLAGS_TABLE: &'static [FlagIndex];
const ORDERED_SINGLE_FLAG_INDICES: &'static [FlagIndex];
const ORDERED_GROUP_FLAG_INDICES: &'static [FlagIndex];
fn new() -> Self;
fn none() -> Self;
fn all() -> Self;
fn union(flags: &[Self]) -> Self;
fn union_without(flags: &[Self], removals: &[Self]) -> Self;
fn try_find(name: &str) -> Option<Self>;
fn find(name: &str) -> Self;
fn find_or(name: &str, default: Self) -> Self;
fn find_or_none(name: &str) -> Self;
fn count_ones(self) -> u32;
fn count_zeros(self) -> u32;
fn get(self, index: u32) -> bool;
fn set(&mut self, index: u32, on: bool) -> &mut Self;
fn swap(&mut self, index: u32, on: bool) -> bool;
fn from_index(index: u32) -> Self;
fn add(&mut self, flag: Self) -> &mut Self;
fn add_all(&mut self, flags: &[Self]) -> &mut Self;
fn remove(&mut self, flag: Self) -> &mut Self;
fn remove_all(&mut self, flags: &[Self]) -> &mut Self;
fn with(self, flag: Self) -> Self;
fn with_all(self, flags: &[Self]) -> Self;
fn without(self, flag: Self) -> Self;
fn without_all(self, flags: &[Self]) -> Self;
fn has_all(self, flag: Self) -> bool;
fn has_none(self, flag: Self) -> bool;
fn has_any(self, flag: Self) -> bool;
fn as_slice(&self) -> &[Self::MaskType];
fn as_mut_slice(&mut self) -> &mut [Self::MaskType];
fn into_inner(self) -> Self::MasksArrayType;
fn as_bytes(&self) -> &[u8];
fn as_mut_bytes(&mut self) -> &mut [u8];
fn to_be_bytes(self) -> Self::BytesArrayType;
fn from_be_bytes(bytes: Self::BytesArrayType) -> Self;
fn to_le_bytes(self) -> Self::BytesArrayType;
fn from_le_bytes(bytes: Self::BytesArrayType) -> Self;
fn to_ne_bytes(self) -> Self::BytesArrayType;
fn from_ne_bytes(bytes: Self::BytesArrayType) -> Self;
fn not(self) -> Self;
fn and(self, other: Self) -> Self;
fn or(self, other: Self) -> Self;
fn xor(self, other: Self) -> Self;
fn nand(self, other: Self) -> Self;
fn nor(self, other: Self) -> Self;
fn xnor(self, other: Self) -> Self;
fn imply(self, other: Self) -> Self;
fn nimply(self, other: Self) -> Self;
fn eq(self, other: Self) -> Self;
fn ne(self, other: Self) -> Self;
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct FlagIndex {
index: u16,
}
impl FlagIndex {
#[must_use]
#[inline(always)]
pub const fn new(index: u16) -> Self {
Self { index }
}
#[must_use]
#[inline(always)]
pub const fn index(self) -> usize {
self.index as _
}
}
#[derive(Debug, Clone, Copy)]
pub struct FlagRow<T: Flags> {
pub name: &'static str,
pub value: T,
sub_flag_indices: Option<&'static [FlagIndex]>,
}
impl<T: Flags> FlagRow<T> {
#[must_use]
#[inline(always)]
pub const fn single(name: &'static str, value: T) -> Self {
Self { name, value, sub_flag_indices: None }
}
#[must_use]
#[inline(always)]
pub const fn group(
name: &'static str,
value: T,
sub_flag_indices: &'static [FlagIndex],
) -> Self {
Self {
name,
value,
sub_flag_indices: Some(sub_flag_indices),
}
}
#[must_use]
#[inline(always)]
pub const fn bits(&self) -> u32 {
if let Some(subflags) = self.sub_flag_indices {
subflags.len() as u32
} else {
1
}
}
#[must_use]
#[inline(always)]
pub const fn sub_flag_indices(&self) -> &'static [FlagIndex] {
if let Some(subflags) = self.sub_flag_indices {
subflags
} else {
&[]
}
}
}
#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct FlagGroupInfo {
pub bits: u32,
pub index: u16,
}
#[derive(Clone)]
pub struct FlagTables<T: Flags, const TABLE_LEN: usize, const SINGLE_COUNT: usize, const GROUP_COUNT: usize> {
pub rows: [FlagRow<T>; TABLE_LEN],
pub name_ordered_row_indices: [FlagIndex; TABLE_LEN],
pub name_ordered_single_indices: [FlagIndex; SINGLE_COUNT],
pub name_ordered_group_indices: [FlagIndex; GROUP_COUNT],
pub bit_ordered_group_indices: [FlagIndex; GROUP_COUNT],
}
#[derive(Clone, Copy)]
pub struct FlagRows<T: Flags> {
pub rows: &'static [FlagRow<T>],
}
impl<T: Flags> FlagRows<T> {
#[must_use]
#[inline(always)]
pub const fn new(rows: &'static [FlagRow<T>]) -> Self {
Self { rows }
}
#[must_use]
#[inline(always)]
pub const fn rows(&self, range: Range<usize>) -> FlagRows<T> {
FlagRows::new(crate::internal::subslice(self.rows, range))
}
#[must_use]
#[inline(always)]
pub const fn row(&self, index: usize) -> &'static FlagRow<T> {
&self.rows[index]
}
}
impl<
T: Flags,
const TABLE_LEN: usize,
const SINGLE_COUNT: usize,
const GROUP_COUNT: usize
> FlagTables<T, TABLE_LEN, SINGLE_COUNT, GROUP_COUNT> {
#[must_use]
#[inline(always)]
pub const fn len() -> usize {
TABLE_LEN
}
#[must_use]
#[inline(always)]
pub const fn single_len() -> usize {
SINGLE_COUNT
}
#[must_use]
#[inline(always)]
pub const fn group_len() -> usize {
GROUP_COUNT
}
#[must_use]
#[inline(always)]
pub const fn singles_range() -> Range<usize> {
0..SINGLE_COUNT
}
#[must_use]
#[inline(always)]
pub const fn groups_range() -> Range<usize> {
SINGLE_COUNT..TABLE_LEN
}
#[must_use]
#[inline(always)]
pub const fn row(&'static self, index: u16) -> &'static FlagRow<T> {
&self.rows[index as usize]
}
#[must_use]
#[inline(always)]
pub const fn rows(&'static self, range: Range<usize>) -> FlagRows<T> {
FlagRows::new(crate::internal::subslice(&self.rows, range))
}
#[must_use]
#[inline(always)]
pub const fn singles(&'static self) -> FlagRows<T> {
self.rows(Self::singles_range())
}
#[must_use]
#[inline(always)]
pub const fn groups(&'static self) -> FlagRows<T> {
self.rows(Self::groups_range())
}
#[must_use]
#[inline(always)]
pub const fn name(&'static self, index: u16) -> &'static str {
self.row(index).name
}
#[must_use]
#[inline(always)]
pub const fn value(&'static self, index: u16) -> T {
self.row(index).value
}
#[inline(always)]
const fn rev_bit_count_search_cmp(lhs: u32, rhs_index: FlagIndex, context: &[FlagRow<T>]) -> ::core::cmp::Ordering {
use ::core::cmp::Ordering::*;
let rhs = context[rhs_index.index()].bits();
if lhs > rhs {
Less
} else if lhs < rhs {
Greater
} else {
Equal
}
}
const_binary_search_fn!(
use Self::rev_bit_count_search_cmp;
#[must_use]
#[inline(always)]
const fn bit_count_binary_search(static u32, static FlagIndex, context: &[FlagRow<T>]) -> usize
);
#[inline]
#[must_use]
#[track_caller]
const fn upper_bit_count_search(&'static self, bits: u32, range: Range<usize>) -> usize {
let start = range.start;
Self::bit_count_binary_search(
bits,
crate::internal::subslice(&self.bit_ordered_group_indices, range),
&self.rows
) + start
}
#[inline]
#[must_use]
#[track_caller]
const fn upper_bit_count_search_full(&'static self, bits: u32) -> usize {
self.upper_bit_count_search(
bits,
0..self.bit_ordered_group_indices.len()
)
}
}
#[derive(Clone)]
pub struct FlagConstants<
T: Flags,
const SINGLE_COUNT: usize,
const GROUP_COUNT: usize,
const TOTAL_COUNT: usize,
> {
pub single_flag_count: usize,
pub group_flag_count: usize,
pub total_flag_count: usize,
pub bits: u32,
pub mask_bits: u32,
pub mask_count: usize,
pub table: FlagTables<T, TOTAL_COUNT, SINGLE_COUNT, GROUP_COUNT>,
}