use core::cell::Cell;
use core::fmt::Debug;
use core::marker::PhantomData;
use core::sync::atomic::AtomicBool;
use core::sync::atomic::AtomicUsize;
use core::sync::atomic::Ordering::Relaxed;
use super::Neu;
use crate::MayDebug;
pub struct Prefix<U, P, T>
where
U: Neu<T>,
P: Neu<T>,
{
prefix: P,
unit: U,
count: Cell<usize>,
value: Cell<bool>,
marker: PhantomData<T>,
}
impl<U, P, T> Debug for Prefix<U, P, T>
where
U: Neu<T> + Debug,
P: Neu<T> + Debug,
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("Prefix")
.field("prefix", &self.prefix)
.field("unit", &self.unit)
.field("count", &self.count)
.field("value", &self.value)
.finish()
}
}
impl<U, P, T> Default for Prefix<U, P, T>
where
U: Neu<T> + Default,
P: Neu<T> + Default,
{
fn default() -> Self {
Self {
prefix: Default::default(),
unit: Default::default(),
count: Default::default(),
value: Default::default(),
marker: Default::default(),
}
}
}
impl<U, P, T> Clone for Prefix<U, P, T>
where
U: Neu<T> + Clone,
P: Neu<T> + Clone,
{
fn clone(&self) -> Self {
Self {
prefix: self.prefix.clone(),
unit: self.unit.clone(),
value: self.value.clone(),
count: self.count.clone(),
marker: self.marker,
}
}
}
impl<U, P, T> Prefix<U, P, T>
where
U: Neu<T>,
P: Neu<T>,
{
pub const fn new(prefix: P, count: usize, unit: U) -> Self {
Self {
prefix,
unit,
count: Cell::new(count),
value: Cell::new(true),
marker: PhantomData,
}
}
pub const fn unit(&self) -> &U {
&self.unit
}
pub const fn prefix(&self) -> &P {
&self.prefix
}
pub const fn unit_mut(&mut self) -> &mut U {
&mut self.unit
}
pub const fn prefix_mut(&mut self) -> &mut P {
&mut self.prefix
}
pub fn set_unit(&mut self, unit: U) -> &mut Self {
self.unit = unit;
self
}
pub fn set_prefix(&mut self, prefix: P) -> &mut Self {
self.prefix = prefix;
self
}
}
impl<U, I, T> Neu<T> for Prefix<U, I, T>
where
U: Neu<T>,
I: Neu<T>,
T: MayDebug,
{
#[inline(always)]
fn is_match(&self, other: &T) -> bool {
let mut value = self.value.get();
if value {
let count = self.count.get();
if count == 0 {
value = self.unit.is_match(other) && value;
crate::trace_retval!("Prefix", other, value);
} else {
value = self.prefix.is_match(other) && value;
crate::trace_retval!("Prefix", count, other, value);
self.value.set(value);
self.count.set(count - 1);
}
}
value
}
fn min_length(&self) -> usize {
0
}
}
pub const fn prefix<T, P, U>(prefix: P, unit: U) -> Prefix<U, P, T>
where
U: Neu<T>,
P: Neu<T>,
{
prefix_cnt(prefix, 1, unit)
}
pub const fn prefix_cnt<T, P, U>(prefix: P, n: usize, unit: U) -> Prefix<U, P, T>
where
U: Neu<T>,
P: Neu<T>,
{
Prefix::new(prefix, n, unit)
}
pub struct PrefixSync<U, P, T>
where
U: Neu<T>,
P: Neu<T>,
{
prefix: P,
unit: U,
count: AtomicUsize,
value: AtomicBool,
marker: PhantomData<T>,
}
impl<U, P, T> Debug for PrefixSync<U, P, T>
where
U: Neu<T> + Debug,
P: Neu<T> + Debug,
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("PrefixSync")
.field("prefix", &self.prefix)
.field("unit", &self.unit)
.field("count", &self.count)
.field("value", &self.value)
.finish()
}
}
impl<U, P, T> Default for PrefixSync<U, P, T>
where
U: Neu<T> + Default,
P: Neu<T> + Default,
{
fn default() -> Self {
Self {
prefix: Default::default(),
unit: Default::default(),
count: Default::default(),
value: Default::default(),
marker: Default::default(),
}
}
}
impl<U, P, T> Clone for PrefixSync<U, P, T>
where
U: Neu<T> + Clone,
P: Neu<T> + Clone,
{
fn clone(&self) -> Self {
Self {
prefix: self.prefix.clone(),
unit: self.unit.clone(),
value: AtomicBool::new(self.value.load(Relaxed)),
count: AtomicUsize::new(self.count.load(Relaxed)),
marker: self.marker,
}
}
}
impl<U, P, T> PrefixSync<U, P, T>
where
U: Neu<T>,
P: Neu<T>,
{
pub const fn new(prefix: P, count: usize, unit: U) -> Self {
Self {
prefix,
unit,
count: AtomicUsize::new(count),
value: AtomicBool::new(true),
marker: PhantomData,
}
}
pub const fn unit(&self) -> &U {
&self.unit
}
pub const fn prefix(&self) -> &P {
&self.prefix
}
pub const fn unit_mut(&mut self) -> &mut U {
&mut self.unit
}
pub const fn prefix_mut(&mut self) -> &mut P {
&mut self.prefix
}
pub fn set_unit(&mut self, unit: U) -> &mut Self {
self.unit = unit;
self
}
pub fn set_prefix(&mut self, prefix: P) -> &mut Self {
self.prefix = prefix;
self
}
}
impl<U, I, T> Neu<T> for PrefixSync<U, I, T>
where
U: Neu<T>,
I: Neu<T>,
T: MayDebug,
{
#[inline(always)]
fn is_match(&self, other: &T) -> bool {
let mut value = self.value.load(Relaxed);
if value {
let count = self.count.load(Relaxed);
if count == 0 {
value = self.unit.is_match(other) && value;
crate::trace_retval!("PrefixSync", other, value);
} else {
value = self.prefix.is_match(other) && value;
crate::trace_retval!("PrefixSync", count, other, value);
self.value.store(value, Relaxed);
self.count.store(count - 1, Relaxed);
}
}
value
}
fn min_length(&self) -> usize {
0
}
}
pub const fn prefix_sync<T, P, U>(prefix: P, unit: U) -> PrefixSync<U, P, T>
where
U: Neu<T>,
P: Neu<T>,
{
prefix_sync_cnt(prefix, 1, unit)
}
pub const fn prefix_sync_cnt<T, P, U>(prefix: P, count: usize, unit: U) -> PrefixSync<U, P, T>
where
U: Neu<T>,
P: Neu<T>,
{
PrefixSync::new(prefix, count, unit)
}