use crate::x11_colors;
#[derive(Default, Clone, Copy, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct Flags {
missing: Missing,
name: u8,
}
#[cfg(test)]
const _: () = const {
if x11_colors::NAMES.len() > 253 {
panic!("There are more X11 color names than can be packed into Flags.");
}
};
#[derive(Default, Clone, Copy, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct Missing(u8);
impl Flags {
#[inline]
pub const fn from_missing(missing: Missing) -> Self {
Self { missing, name: 0 }
}
#[inline]
#[warn(
clippy::missing_const_for_fn,
reason = "can be made const with MSRV 1.83"
)]
pub fn set_missing(&mut self, missing: Missing) {
self.missing = missing;
}
#[inline]
pub const fn missing(self) -> Missing {
self.missing
}
pub(crate) fn set_named_color(&mut self, name_ix: usize) {
debug_assert!(
name_ix < x11_colors::NAMES.len(),
"Expected an X11 color name index no larger than: {}. Got: {}.",
x11_colors::NAMES.len(),
name_ix
);
#[expect(
clippy::cast_possible_truncation,
reason = "name_ix is guaranteed to small enough by the above condition and by the test on the length of `x11_colors::NAMES`"
)]
{
self.name = name_ix as u8 + 1;
}
}
#[warn(
clippy::missing_const_for_fn,
reason = "can be made const with MSRV 1.83"
)]
pub(crate) fn set_named_color_space(&mut self) {
self.name = 255;
}
#[inline]
pub const fn named(self) -> bool {
self.name != 0
}
pub const fn color_name(self) -> Option<&'static str> {
let name_ix = self.name;
if name_ix == 0 || name_ix == 255 {
None
} else {
Some(x11_colors::NAMES[name_ix as usize - 1])
}
}
#[inline]
#[warn(
clippy::missing_const_for_fn,
reason = "can be made const with MSRV 1.83"
)]
pub fn discard_name(&mut self) {
self.name = 0;
}
}
impl core::fmt::Debug for Flags {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("Flags")
.field("missing", &self.missing)
.field("name", &self.name)
.field("named", &self.named())
.field("color_name", &self.color_name())
.finish()
}
}
impl Missing {
pub const EMPTY: Self = Self(0);
#[inline]
pub const fn single(ix: usize) -> Self {
debug_assert!(ix <= 3, "color component index must be 0, 1, 2 or 3");
Self(1 << ix)
}
#[inline]
pub const fn contains(self, ix: usize) -> bool {
(self.0 & Self::single(ix).0) != 0
}
#[inline]
#[warn(
clippy::missing_const_for_fn,
reason = "can be made const with MSRV 1.83"
)]
pub fn insert(&mut self, ix: usize) {
self.0 |= Self::single(ix).0;
}
#[inline]
pub const fn is_empty(self) -> bool {
self.0 == 0
}
}
impl core::ops::BitAnd for Missing {
type Output = Self;
#[inline]
fn bitand(self, rhs: Self) -> Self {
Self(self.0 & rhs.0)
}
}
impl core::ops::BitOr for Missing {
type Output = Self;
#[inline]
fn bitor(self, rhs: Self) -> Self {
Self(self.0 | rhs.0)
}
}
impl core::ops::Not for Missing {
type Output = Self;
#[inline]
fn not(self) -> Self::Output {
Self(!self.0)
}
}
impl core::fmt::Debug for Missing {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_tuple("Missing")
.field(&format_args!("{:#010b}", self.0))
.finish()
}
}