#[cfg(all(test, feature = "support_panic_trig"))]
use crate::core::trig::panic::PanicTrigManuallyDrop;
use core::fmt::Display;
use crate::core::trig::TrigManuallyDrop;
use core::fmt::Debug;
use core::sync::atomic::Ordering;
use core::sync::atomic::AtomicU8;
const READ_ORDERING_METHOD: Ordering = Ordering::SeqCst;
const WRITE_ORDERING_METHOD: Ordering = Ordering::SeqCst;
#[repr(transparent)]
pub struct StateManuallyDrop {
state: AtomicU8,
}
impl Clone for StateManuallyDrop {
#[inline]
fn clone(&self) -> Self {
Self {
state: AtomicU8::new(self.__read_byte())
}
}
}
impl Debug for StateManuallyDrop {
#[inline]
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
f.debug_struct("StateManuallyDrop")
.field("state", &self.read())
.finish()
}
}
impl Display for StateManuallyDrop {
#[inline(always)]
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
Display::fmt(&self.read(), f)
}
}
#[repr(u8)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum StateManuallyDropData {
Empty = 1,
TakeModeTrig = 5,
DropModeTrig = 15,
IntoInnerModeTrig = 25,
IgnoreTrigWhenDrop = 30,
}
impl Display for StateManuallyDropData {
#[inline]
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
let str = match self {
Self::Empty => "Empty",
Self::TakeModeTrig => "TakeModeTrig",
Self::DropModeTrig => "DropModeTrig",
Self::IntoInnerModeTrig => "IntoInnerModeTrig",
Self::IgnoreTrigWhenDrop => "IgnoreTrigWhenDrop",
};
Display::fmt(str, f)
}
}
impl From<u8> for StateManuallyDropData {
#[inline(always)]
fn from(a: u8) -> Self {
StateManuallyDropData::from_or_empty(a)
}
}
impl Default for StateManuallyDropData {
#[inline(always)]
fn default() -> Self {
Self::empty()
}
}
impl StateManuallyDropData {
#[inline(always)]
pub const fn into(self) -> u8 {
self as _
}
#[inline]
pub fn from_or_empty(a: u8) -> Self {
Self::is_valid_byte_fn(
a,
|| unsafe {
Self::force_from(a)
},
|| Self::empty()
)
}
#[inline]
pub fn from(a: u8) -> Option<Self> {
Self::is_valid_byte_fn(
a,
|| {
let sself = unsafe {
Self::force_from(a)
};
Some(sself)
},
|| None
)
}
#[inline(always)]
const fn __empty() -> Self {
let sself = Self::Empty;
sself
}
#[inline(always)]
pub const fn empty() -> Self {
Self::__empty()
}
#[inline(always)]
pub const fn no_panic_state() -> Self {
Self::empty()
}
#[inline(always)]
pub fn is_valid_byte_fn<R>(a: u8, next: impl FnOnce() -> R, errf: impl FnOnce() -> R) -> R {
match a {
a if a == Self::Empty as _ ||
a == Self::TakeModeTrig as _ ||
a == Self::DropModeTrig as _ ||
a == Self::IntoInnerModeTrig as _ ||
a == Self::IgnoreTrigWhenDrop as _ => next(),
_ => errf()
}
}
#[inline]
pub fn is_valid_byte(a: u8) -> bool {
Self::is_valid_byte_fn(
a,
|| true,
|| false,
)
}
#[inline(always)]
pub unsafe fn force_from(a: u8) -> Self {
crate::__fullinternal_debug_assertions!(
Self::is_valid_byte(a),
true
);
Self::__force_form(a)
}
#[inline(always)]
const fn __force_form(a: u8) -> Self {
let result: StateManuallyDropData = unsafe {
core::mem::transmute(a as u8)
};
result
}
#[inline(always)]
pub const fn is_next_trig(&self) -> bool {
match self {
StateManuallyDropData::Empty => false,
_ => true,
}
}
#[inline(always)]
pub const fn is_empty(&self) -> bool {
match self {
StateManuallyDropData::Empty => true,
_ => false,
}
}
}
pub const EMPTY_STATE: StateManuallyDrop = StateManuallyDrop::__empty();
impl StateManuallyDrop {
#[inline(always)]
pub fn empty() -> Self {
let sself = Self::__empty();
crate::__fullinternal_debug_assertions!(sself.is_empty(), true);
crate::__fullinternal_debug_assertions!(sself.is_next_trig(), false);
sself
}
#[inline(always)]
const fn __empty() -> Self {
Self {
state: AtomicU8::new(StateManuallyDropData::empty() as _)
}
}
#[inline(always)]
pub fn is_empty(&self) -> bool {
self.read().is_empty()
}
#[inline(always)]
fn __read_byte(&self) -> u8 {
self.state.load(READ_ORDERING_METHOD)
}
#[inline(always)]
pub fn read(&self) -> StateManuallyDropData {
let byte = self.__read_byte();
unsafe {
StateManuallyDropData::force_from(byte)
}
}
#[inline(always)]
fn __force_write(&self, a: StateManuallyDropData) -> StateManuallyDropData {
let byte = self.state.swap(a as _, WRITE_ORDERING_METHOD);
unsafe {
StateManuallyDropData::force_from(byte)
}
}
pub unsafe fn get_and_reset(&self) -> StateManuallyDropData {
let old_value = self.__force_write(
StateManuallyDropData::Empty
);
crate::__fullinternal_debug_assertions!(self.is_empty(), true);
crate::__fullinternal_debug_assertions!(self.is_next_trig(), false);
old_value
}
#[inline]
fn __safe_replace_mutstate<Trig: TrigManuallyDrop>(&self, new_state: StateManuallyDropData) {
crate::__fullinternal_debug_assertions!(new_state.is_next_trig(), true);
let old_state = self.__force_write(new_state);
if old_state.is_next_trig() {
Trig::trig_next_invalid_beh(
format_args!(
"Undefined behavior when using ManuallyDrop(combo_replace_manudropstate), instead of the expected default state, the current state: {:?}.",
old_state
)
);
}
}
#[inline(always)]
pub fn to_dropmode_or_trig<Trig: TrigManuallyDrop>(&self) {
self.__safe_replace_mutstate::<Trig>(
StateManuallyDropData::DropModeTrig
);
crate::__fullinternal_debug_assertions!(self.is_next_trig(), true);
}
#[inline(always)]
pub fn to_takemode_or_trig<Trig: TrigManuallyDrop>(&self) {
self.__safe_replace_mutstate::<Trig>(
StateManuallyDropData::TakeModeTrig
);
crate::__fullinternal_debug_assertions!(self.is_next_trig(), true);
}
#[inline(always)]
pub fn to_ignore_trig_when_drop<Trig: TrigManuallyDrop>(&self) {
self.__safe_replace_mutstate::<Trig>(
StateManuallyDropData::IgnoreTrigWhenDrop
);
crate::__fullinternal_debug_assertions!(self.is_next_trig(), true);
}
#[inline(always)]
pub fn to_intoinnermode_or_trig<Trig: TrigManuallyDrop>(&self) {
self.__safe_replace_mutstate::<Trig>(
StateManuallyDropData::IntoInnerModeTrig
);
crate::__fullinternal_debug_assertions!(self.is_next_trig(), true);
}
#[inline(always)]
pub fn deref_or_trig<Trig: TrigManuallyDrop>(&self) {
let a_state = self.read();
if a_state.is_next_trig() {
Trig::trig_next_invalid_beh(
format_args!(
"Undefined behavior when using ManuallyDrop.deref(), instead of the expected default state, the current state: {:?}.",
a_state
)
)
}
}
pub fn if_empty_then_run_trigfn<Trig: TrigManuallyDrop, F: FnOnce()>(&self, exp_str: &'static str, fn_trig: F) {
let a_state = self.read();
if a_state.is_empty() {
fn_trig();
Trig::trig_next_invalid_beh(
format_args!(
"Undefined behavior when using ManuallyDrop ({}), state should not be default, current state is {:?}.",
exp_str,
a_state
)
)
}
}
#[inline(always)]
pub fn is_next_trig(&self) -> bool {
self.read().is_next_trig()
}
}
impl Default for StateManuallyDrop {
#[inline(always)]
fn default() -> Self {
StateManuallyDrop::empty()
}
}
#[cfg(all(test, feature = "support_panic_trig"))]
#[test]
fn test_state() {
let state = StateManuallyDrop::empty();
assert_eq!(state.is_empty(), true);
assert_eq!(state.is_next_trig(), false);
state.deref_or_trig::<PanicTrigManuallyDrop>(); }
#[cfg(all(test, feature = "support_panic_trig"))]
#[test]
fn test_const_empty_state() {
let state = EMPTY_STATE; assert_eq!(state.is_empty(), true);
assert_eq!(state.is_next_trig(), false);
state.deref_or_trig::<PanicTrigManuallyDrop>(); }
#[cfg(all(test, feature = "support_panic_trig"))]
#[test]
fn test_reset() {
let state = StateManuallyDrop::empty();
assert_eq!(state.is_empty(), true);
assert_eq!(state.is_next_trig(), false);
state.deref_or_trig::<PanicTrigManuallyDrop>(); state.to_dropmode_or_trig::<PanicTrigManuallyDrop>();
assert_eq!(state.is_empty(), false);
assert_eq!(state.is_next_trig(), true);
let old_state = unsafe {
state.get_and_reset()
};
assert_eq!(state.is_empty(), true);
assert_eq!(state.is_next_trig(), false);
assert_eq!(old_state.is_empty(), false);
assert_eq!(old_state.is_next_trig(), true);
assert_eq!(old_state, StateManuallyDropData::DropModeTrig);
}