SafeManuallyDrop/core/
state.rs1
2#[cfg(all(test, feature = "support_panic_trig"))]
5use crate::core::trig::panic::PanicTrigManuallyDrop;
6use core::fmt::Display;
7use crate::core::trig::TrigManuallyDrop;
8use core::fmt::Debug;
9use core::sync::atomic::Ordering;
10use core::sync::atomic::AtomicU8;
11
12const READ_ORDERING_METHOD: Ordering = Ordering::SeqCst;
13const WRITE_ORDERING_METHOD: Ordering = Ordering::SeqCst; #[repr(transparent)]
17pub struct StateManuallyDrop {
18 state: AtomicU8,
19}
20
21impl Clone for StateManuallyDrop {
22 #[inline]
23 fn clone(&self) -> Self {
24 Self {
25 state: AtomicU8::new(self.__read_byte())
26 }
27 }
28}
29
30impl Debug for StateManuallyDrop {
31 #[inline]
32 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
33 f.debug_struct("StateManuallyDrop")
34 .field("state", &self.read())
35 .finish()
36 }
37}
38
39impl Display for StateManuallyDrop {
40 #[inline(always)]
41 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
42 Display::fmt(&self.read(), f)
43 }
44}
45
46#[repr(u8)]
48#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
49pub enum StateManuallyDropData {
50 Empty = 1,
53
54 TakeModeTrig = 5,
57 DropModeTrig = 15,
60 IntoInnerModeTrig = 25,
63
64 IgnoreTrigWhenDrop = 30,
67}
68
69impl Display for StateManuallyDropData {
70 #[inline]
71 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
72 let str = match self {
73 Self::Empty => "Empty",
74
75 Self::TakeModeTrig => "TakeModeTrig",
76 Self::DropModeTrig => "DropModeTrig",
77 Self::IntoInnerModeTrig => "IntoInnerModeTrig",
78
79 Self::IgnoreTrigWhenDrop => "IgnoreTrigWhenDrop",
80 };
81
82 Display::fmt(str, f)
83 }
84}
85
86impl From<u8> for StateManuallyDropData {
87 #[inline(always)]
88 fn from(a: u8) -> Self {
89 StateManuallyDropData::from_or_empty(a)
90 }
91}
92
93impl Default for StateManuallyDropData {
94 #[inline(always)]
95 fn default() -> Self {
96 Self::empty()
97 }
98}
99
100impl StateManuallyDropData {
101 #[inline(always)]
103 pub const fn into(self) -> u8 {
104 self as _
105 }
106
107 #[inline]
110 pub fn from_or_empty(a: u8) -> Self {
111 Self::is_valid_byte_fn(
112 a,
113 || unsafe {
114 Self::force_from(a)
115 },
116 || Self::empty()
117 )
118 }
119
120 #[inline]
122 pub fn from(a: u8) -> Option<Self> {
123 Self::is_valid_byte_fn(
124 a,
125 || {
126 let sself = unsafe {
127 Self::force_from(a)
128 };
129
130 Some(sself)
131 },
132 || None
133 )
134 }
135
136 #[inline(always)]
138 const fn __empty() -> Self {
139 let sself = Self::Empty;
140 sself
141 }
142
143 #[inline(always)]
145 pub const fn empty() -> Self {
146 Self::__empty()
147 }
148
149 #[inline(always)]
151 pub const fn no_panic_state() -> Self {
152 Self::empty()
153 }
154
155 #[inline(always)]
157 pub fn is_valid_byte_fn<R>(a: u8, next: impl FnOnce() -> R, errf: impl FnOnce() -> R) -> R {
158 match a {
159 a if a == Self::Empty as _ ||
160
161 a == Self::TakeModeTrig as _ ||
162 a == Self::DropModeTrig as _ ||
163 a == Self::IntoInnerModeTrig as _ ||
164
165 a == Self::IgnoreTrigWhenDrop as _ => next(),
166 _ => errf()
167 }
168 }
169
170 #[inline]
173 pub fn is_valid_byte(a: u8) -> bool {
174 Self::is_valid_byte_fn(
175 a,
176 || true,
177 || false,
178 )
179 }
180
181 #[inline(always)]
184 pub unsafe fn force_from(a: u8) -> Self {
185 crate::__fullinternal_debug_assertions!(
186 Self::is_valid_byte(a),
187 true
188 );
189
190 Self::__force_form(a)
191 }
192
193 #[inline(always)]
196 const fn __force_form(a: u8) -> Self {
197 let result: StateManuallyDropData = unsafe {
198 core::mem::transmute(a as u8)
200 };
201 result
202 }
203
204 #[inline(always)]
206 pub const fn is_next_trig(&self) -> bool {
207 match self {
208 StateManuallyDropData::Empty => false,
209 _ => true,
210 }
211 }
212
213 #[inline(always)]
215 pub const fn is_empty(&self) -> bool {
216 match self {
217 StateManuallyDropData::Empty => true,
218 _ => false,
219 }
220 }
221}
222
223pub const EMPTY_STATE: StateManuallyDrop = StateManuallyDrop::__empty();
225
226impl StateManuallyDrop {
227 #[inline(always)]
229 pub fn empty() -> Self {
230 let sself = Self::__empty();
231
232 crate::__fullinternal_debug_assertions!(sself.is_empty(), true);
233 crate::__fullinternal_debug_assertions!(sself.is_next_trig(), false);
234
235 sself
236 }
237
238 #[inline(always)]
240 const fn __empty() -> Self {
241 Self {
242 state: AtomicU8::new(StateManuallyDropData::empty() as _)
243 }
244 }
245
246 #[inline(always)]
248 pub fn is_empty(&self) -> bool {
249 self.read().is_empty()
250 }
251
252 #[inline(always)]
254 fn __read_byte(&self) -> u8 {
255 self.state.load(READ_ORDERING_METHOD)
256 }
257
258 #[inline(always)]
260 pub fn read(&self) -> StateManuallyDropData {
261 let byte = self.__read_byte();
262 unsafe {
263 StateManuallyDropData::force_from(byte)
264 }
265 }
266
267 #[inline(always)]
270 fn __force_write(&self, a: StateManuallyDropData) -> StateManuallyDropData {
271 let byte = self.state.swap(a as _, WRITE_ORDERING_METHOD);
272 unsafe {
273 StateManuallyDropData::force_from(byte)
274 }
275 }
276
277 pub unsafe fn get_and_reset(&self) -> StateManuallyDropData {
279 let old_value = self.__force_write(
280 StateManuallyDropData::Empty
281 );
282 crate::__fullinternal_debug_assertions!(self.is_empty(), true);
283 crate::__fullinternal_debug_assertions!(self.is_next_trig(), false);
284
285 old_value
286 }
287
288 #[inline]
291 fn __safe_replace_mutstate<Trig: TrigManuallyDrop>(&self, new_state: StateManuallyDropData) {
292 crate::__fullinternal_debug_assertions!(new_state.is_next_trig(), true);
293
294 let old_state = self.__force_write(new_state);
295
296 if old_state.is_next_trig() {
298 Trig::trig_next_invalid_beh(
299 format_args!(
300 "Undefined behavior when using ManuallyDrop(combo_replace_manudropstate), instead of the expected default state, the current state: {:?}.",
301 old_state
302 )
303 );
304 }
305 }
306
307 #[inline(always)]
310 pub fn to_dropmode_or_trig<Trig: TrigManuallyDrop>(&self) {
311 self.__safe_replace_mutstate::<Trig>(
312 StateManuallyDropData::DropModeTrig
313 );
314
315 crate::__fullinternal_debug_assertions!(self.is_next_trig(), true);
316 }
317
318 #[inline(always)]
321 pub fn to_takemode_or_trig<Trig: TrigManuallyDrop>(&self) {
322 self.__safe_replace_mutstate::<Trig>(
323 StateManuallyDropData::TakeModeTrig
324 );
325
326 crate::__fullinternal_debug_assertions!(self.is_next_trig(), true);
327 }
328
329 #[inline(always)]
332 pub fn to_ignore_trig_when_drop<Trig: TrigManuallyDrop>(&self) {
333 self.__safe_replace_mutstate::<Trig>(
334 StateManuallyDropData::IgnoreTrigWhenDrop
335 );
336
337 crate::__fullinternal_debug_assertions!(self.is_next_trig(), true);
338 }
339
340 #[inline(always)]
343 pub fn to_intoinnermode_or_trig<Trig: TrigManuallyDrop>(&self) {
344 self.__safe_replace_mutstate::<Trig>(
345 StateManuallyDropData::IntoInnerModeTrig
346 );
347
348 crate::__fullinternal_debug_assertions!(self.is_next_trig(), true);
349 }
350
351 #[inline(always)]
354 pub fn deref_or_trig<Trig: TrigManuallyDrop>(&self) {
355 let a_state = self.read();
356
357 if a_state.is_next_trig() {
358 Trig::trig_next_invalid_beh(
359 format_args!(
360 "Undefined behavior when using ManuallyDrop.deref(), instead of the expected default state, the current state: {:?}.",
361 a_state
362 )
363 )
364 }
365 }
366
367 pub fn if_empty_then_run_trigfn<Trig: TrigManuallyDrop, F: FnOnce()>(&self, exp_str: &'static str, fn_trig: F) {
370 let a_state = self.read();
371
372 if a_state.is_empty() {
373 fn_trig();
374
375 Trig::trig_next_invalid_beh(
376 format_args!(
377 "Undefined behavior when using ManuallyDrop ({}), state should not be default, current state is {:?}.",
378 exp_str,
379 a_state
380 )
381 )
382 }
383 }
384
385 #[inline(always)]
387 pub fn is_next_trig(&self) -> bool {
388 self.read().is_next_trig()
389 }
390}
391
392impl Default for StateManuallyDrop {
393 #[inline(always)]
394 fn default() -> Self {
395 StateManuallyDrop::empty()
396 }
397}
398
399#[cfg(all(test, feature = "support_panic_trig"))]
400#[test]
401fn test_state() {
402 let state = StateManuallyDrop::empty();
403 assert_eq!(state.is_empty(), true);
404 assert_eq!(state.is_next_trig(), false);
405
406 state.deref_or_trig::<PanicTrigManuallyDrop>(); }
408
409#[cfg(all(test, feature = "support_panic_trig"))]
410#[test]
411fn test_const_empty_state() {
412 let state = EMPTY_STATE; assert_eq!(state.is_empty(), true);
414 assert_eq!(state.is_next_trig(), false);
415
416 state.deref_or_trig::<PanicTrigManuallyDrop>(); }
418
419
420#[cfg(all(test, feature = "support_panic_trig"))]
421#[test]
422fn test_reset() {
423 let state = StateManuallyDrop::empty();
424 assert_eq!(state.is_empty(), true);
425 assert_eq!(state.is_next_trig(), false);
426
427 state.deref_or_trig::<PanicTrigManuallyDrop>(); state.to_dropmode_or_trig::<PanicTrigManuallyDrop>();
429
430 assert_eq!(state.is_empty(), false);
431 assert_eq!(state.is_next_trig(), true);
432
433 let old_state = unsafe {
434 state.get_and_reset()
435 };
436 assert_eq!(state.is_empty(), true);
437 assert_eq!(state.is_next_trig(), false);
438 assert_eq!(old_state.is_empty(), false);
439 assert_eq!(old_state.is_next_trig(), true);
440 assert_eq!(old_state, StateManuallyDropData::DropModeTrig);
441}
442