use core::fmt::{Debug, Formatter};
use core::sync::atomic::Ordering;
use crate::protocol::{Behold, Sequence};
#[cfg(not(feature = "alloc"))]
use no_std::_Sequencer;
#[cfg(feature = "alloc")]
use standard::_Sequencer;
pub trait IntoSequencer {
fn into_sequencer(self) -> Sequencer;
}
pub struct Sequencer(_Sequencer);
impl Sequencer {
#[inline(always)]
pub fn new() -> Self {
Self::init(0)
}
#[inline(always)]
pub fn init(value: Sequence) -> Self {
Self(_Sequencer::init_with(value))
}
#[inline(always)]
pub fn fork(&self) -> Self {
Self::init(self.current())
}
#[cfg(feature = "alloc")]
pub fn join(&self, other: &mut Sequencer) {
self.sync(other);
other.0 = self.0.clone();
}
#[inline(always)]
pub fn sync(&self, other: &Sequencer) {
self.rewind(other.current())
}
#[inline(always)]
pub fn next(&self) -> Sequence {
self.next_value()
}
#[inline(always)]
pub fn current(&self) -> Sequence {
self.0 .0.load(Ordering::Acquire)
}
#[inline(always)]
pub fn rewind(&self, value: Sequence) {
self.0 .0.store(value, Ordering::Release)
}
#[inline(always)]
pub fn advance(&self, increment: Sequence) -> Behold<Sequence> {
Behold::new(self.0 .0.fetch_add(increment, Ordering::Release) + increment)
}
#[inline]
fn next_value(&self) -> Sequence {
self.0 .0.fetch_add(1, Ordering::Release)
}
}
#[cfg(feature = "serde")]
impl serde::Serialize for Sequencer {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_u8(self.current())
}
}
#[cfg(feature = "serde")]
impl<'de> serde::Deserialize<'de> for Sequencer {
fn deserialize<D: serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
let value = u8::deserialize(d)?;
Ok(Sequencer::init(value))
}
}
impl IntoSequencer for Sequencer {
#[inline(always)]
fn into_sequencer(self) -> Sequencer {
self
}
}
#[cfg(not(feature = "alloc"))]
impl IntoSequencer for &Sequencer {
#[inline(always)]
fn into_sequencer(self) -> Sequencer {
self.fork()
}
}
#[cfg(feature = "alloc")]
impl IntoSequencer for &Sequencer {
#[inline(always)]
fn into_sequencer(self) -> Sequencer {
self.clone()
}
}
impl IntoSequencer for Sequence {
#[inline]
fn into_sequencer(self) -> Sequencer {
Sequencer::init(self)
}
}
impl From<&Sequencer> for Sequencer {
fn from(value: &Sequencer) -> Self {
value.into_sequencer()
}
}
impl From<Sequence> for Sequencer {
fn from(value: Sequence) -> Self {
value.into_sequencer()
}
}
#[cfg(feature = "alloc")]
impl Clone for Sequencer {
fn clone(&self) -> Self {
Self(self.0.clone())
}
}
impl Default for Sequencer {
fn default() -> Self {
Self::new()
}
}
impl Iterator for Sequencer {
type Item = Sequence;
fn next(&mut self) -> Option<Self::Item> {
Some(self.next_value())
}
}
impl Debug for Sequencer {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
f.debug_tuple("Sequencer").field(&self.current()).finish()
}
}
#[cfg(feature = "alloc")]
mod standard {
use alloc::sync::Arc;
use core::sync::atomic::AtomicU8;
use crate::protocol::Sequence;
#[derive(Clone)]
pub struct _Sequencer(pub(super) Arc<AtomicU8>);
impl _Sequencer {
#[inline]
pub(super) fn init_with(value: Sequence) -> Self {
Self(Arc::new(AtomicU8::new(value)))
}
}
}
#[cfg(not(feature = "alloc"))]
mod no_std {
use core::sync::atomic::AtomicU8;
use crate::protocol::Sequence;
pub struct _Sequencer(pub(super) AtomicU8);
impl _Sequencer {
#[inline]
pub(super) fn init_with(value: Sequence) -> Self {
Self(AtomicU8::new(value))
}
}
}