use std::fmt;
mod bit {
pub(super) const IMPERSONATION: u8 = 1 << 0;
pub(super) const ERROR_MODE: u8 = 1 << 1;
pub(super) const TRANSACTION: u8 = 1 << 2;
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum CapturableAspect {
Impersonation,
ErrorMode,
Transaction,
}
impl CapturableAspect {
pub const EVERY: &'static [Self] = &[Self::Impersonation, Self::ErrorMode, Self::Transaction];
const fn bit(self) -> u8 {
match self {
Self::Impersonation => bit::IMPERSONATION,
Self::ErrorMode => bit::ERROR_MODE,
Self::Transaction => bit::TRANSACTION,
}
}
#[must_use]
pub const fn as_set(self) -> CaptureSet {
CaptureSet { bits: self.bit() }
}
}
impl fmt::Display for CapturableAspect {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(match self {
Self::Impersonation => "impersonation",
Self::ErrorMode => "error mode",
Self::Transaction => "transaction",
})
}
}
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
pub struct CaptureSet {
bits: u8,
}
const fn derive_all() -> CaptureSet {
let mut bits = 0u8;
let mut index = 0;
while index < CapturableAspect::EVERY.len() {
bits |= CapturableAspect::EVERY[index].bit();
index += 1;
}
CaptureSet { bits }
}
impl CaptureSet {
pub const NONE: Self = Self { bits: 0 };
pub const IMPERSONATION: Self = CapturableAspect::Impersonation.as_set();
pub const ERROR_MODE: Self = CapturableAspect::ErrorMode.as_set();
pub const TRANSACTION: Self = CapturableAspect::Transaction.as_set();
pub const DEFAULT: Self = Self {
bits: bit::IMPERSONATION | bit::ERROR_MODE,
};
pub const ALL: Self = derive_all();
#[must_use]
pub const fn union(self, other: Self) -> Self {
Self {
bits: self.bits | other.bits,
}
}
#[must_use]
pub const fn without(self, other: Self) -> Self {
Self {
bits: self.bits & !other.bits,
}
}
#[must_use]
pub const fn contains(self, other: Self) -> bool {
self.bits & other.bits == other.bits
}
#[must_use]
pub const fn is_empty(self) -> bool {
self.bits == 0
}
pub fn aspects(self) -> impl Iterator<Item = CapturableAspect> {
CapturableAspect::EVERY
.iter()
.copied()
.filter(move |aspect| self.bits & aspect.bit() != 0)
}
}
impl fmt::Debug for CaptureSet {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.is_empty() {
return f.write_str("CaptureSet(none)");
}
f.write_str("CaptureSet(")?;
for (index, aspect) in self.aspects().enumerate() {
if index > 0 {
f.write_str(", ")?;
}
write!(f, "{aspect}")?;
}
f.write_str(")")
}
}
impl From<CapturableAspect> for CaptureSet {
fn from(aspect: CapturableAspect) -> Self {
aspect.as_set()
}
}
#[cfg(test)]
mod tests;