use serde::Deserialize;
use serde::Serialize;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[repr(transparent)]
pub struct AttributeFlags(u8);
impl AttributeFlags {
pub const TARGET_CLASS: AttributeFlags = AttributeFlags(1 << 0);
pub const TARGET_FUNCTION: AttributeFlags = AttributeFlags(1 << 1);
pub const TARGET_METHOD: AttributeFlags = AttributeFlags(1 << 2);
pub const TARGET_PROPERTY: AttributeFlags = AttributeFlags(1 << 3);
pub const TARGET_CLASS_CONSTANT: AttributeFlags = AttributeFlags(1 << 4);
pub const TARGET_PARAMETER: AttributeFlags = AttributeFlags(1 << 5);
pub const TARGET_CONSTANT: AttributeFlags = AttributeFlags(1 << 6);
pub const TARGET_ALL: AttributeFlags =
AttributeFlags((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6));
pub const IS_REPEATABLE: AttributeFlags = AttributeFlags(1 << 7);
}
impl AttributeFlags {
#[inline]
#[must_use]
pub const fn empty() -> Self {
AttributeFlags(0)
}
#[inline]
#[must_use]
pub const fn from_bits(bits: u8) -> Self {
AttributeFlags(bits)
}
#[inline]
pub const fn insert(&mut self, other: AttributeFlags) {
self.0 |= other.0;
}
#[inline]
pub const fn set(&mut self, other: AttributeFlags, value: bool) {
if value {
self.insert(other);
} else {
self.0 &= !other.0;
}
}
#[inline]
pub const fn contains(self, other: AttributeFlags) -> bool {
(self.0 & other.0) == other.0
}
#[inline]
pub const fn remove(&mut self, other: AttributeFlags) {
self.0 &= !other.0;
}
#[inline]
pub const fn intersects(self, other: AttributeFlags) -> bool {
(self.0 & other.0) != 0
}
#[inline]
#[must_use]
pub const fn union(&self, other: AttributeFlags) -> AttributeFlags {
AttributeFlags(self.0 | other.0)
}
#[inline]
#[must_use]
pub const fn intersection(&self, other: AttributeFlags) -> AttributeFlags {
AttributeFlags(self.0 & other.0)
}
#[inline]
pub const fn bits(self) -> u8 {
self.0
}
#[inline]
#[must_use]
pub const fn all() -> Self {
Self(Self::TARGET_ALL.0 | Self::IS_REPEATABLE.0)
}
}
impl AttributeFlags {
#[must_use]
pub const fn is_repeatable(&self) -> bool {
self.contains(Self::IS_REPEATABLE)
}
#[must_use]
pub const fn targets_class(&self) -> bool {
self.contains(Self::TARGET_CLASS)
}
#[must_use]
pub const fn targets_function(&self) -> bool {
self.contains(Self::TARGET_FUNCTION)
}
#[must_use]
pub const fn targets_method(&self) -> bool {
self.contains(Self::TARGET_METHOD)
}
#[must_use]
pub const fn targets_property(&self) -> bool {
self.contains(Self::TARGET_PROPERTY)
}
#[must_use]
pub const fn targets_class_constant(&self) -> bool {
self.contains(Self::TARGET_CLASS_CONSTANT)
}
#[must_use]
pub const fn targets_parameter(&self) -> bool {
self.contains(Self::TARGET_PARAMETER)
}
#[must_use]
pub const fn targets_constant(&self) -> bool {
self.contains(Self::TARGET_CONSTANT)
}
#[must_use]
pub fn get_target_names(&self) -> Vec<&'static str> {
let mut targets = Vec::with_capacity(7);
if self.targets_class() {
targets.push("classes");
}
if self.targets_function() {
targets.push("functions");
}
if self.targets_method() {
targets.push("methods");
}
if self.targets_property() {
targets.push("properties");
}
if self.targets_class_constant() {
targets.push("class constants");
}
if self.targets_parameter() {
targets.push("parameters");
}
if self.targets_constant() {
targets.push("global constants");
}
targets
}
}
impl std::ops::BitOr for AttributeFlags {
type Output = Self;
#[inline]
fn bitor(self, rhs: Self) -> Self::Output {
AttributeFlags(self.0 | rhs.0)
}
}
impl std::ops::BitAnd for AttributeFlags {
type Output = Self;
#[inline]
fn bitand(self, rhs: Self) -> Self::Output {
AttributeFlags(self.0 & rhs.0)
}
}
impl std::ops::BitXor for AttributeFlags {
type Output = Self;
#[inline]
fn bitxor(self, rhs: Self) -> Self::Output {
AttributeFlags(self.0 ^ rhs.0)
}
}
impl std::ops::Not for AttributeFlags {
type Output = Self;
#[inline]
fn not(self) -> Self::Output {
AttributeFlags(!self.0)
}
}
impl std::ops::BitOrAssign for AttributeFlags {
#[inline]
fn bitor_assign(&mut self, rhs: Self) {
self.0 |= rhs.0;
}
}
impl std::ops::BitAndAssign for AttributeFlags {
#[inline]
fn bitand_assign(&mut self, rhs: Self) {
self.0 &= rhs.0;
}
}
impl std::ops::BitXorAssign for AttributeFlags {
#[inline]
fn bitxor_assign(&mut self, rhs: Self) {
self.0 ^= rhs.0;
}
}