fast_able/
static_type_std.rs1use std::{
2 cell::UnsafeCell,
3 fmt::{Debug, Display},
4 mem::ManuallyDrop,
5 ops::{Deref, DerefMut},
6};
7
8pub struct StaticTypeForStd<T, F = fn() -> T> {
11 val: UnsafeCell<Option<T>>,
12 is_init_lock: spin::Mutex<bool>,
13 call_fun: UnsafeCell<ManuallyDrop<F>>,
14}
15
16impl<T, F: FnOnce() -> T> StaticTypeForStd<T, F> {
17 pub const fn new(init_fun: F) -> StaticTypeForStd<T, F> {
18 Self {
19 val: UnsafeCell::new(None),
20 is_init_lock: spin::Mutex::new(false),
21 call_fun: UnsafeCell::new(ManuallyDrop::new(init_fun)),
22 }
23 }
24
25 pub fn init_static(&self) {
26 let mut lock = self.is_init_lock.lock();
27 if !*lock {
28 unsafe {
29 let f = ManuallyDrop::take(&mut *self.call_fun.get());
30 *self.val.get() = Some(f());
31 }
32 *lock = true;
33 } else {
34 }
36 }
37}
38
39impl<T, F> StaticTypeForStd<T, F> {
40 #[must_use]
41 pub fn is_init(&self) -> bool {
42 *self.is_init_lock.lock()
43 }
44
45 #[inline(always)]
47 pub fn get_static(&self) -> Option<&T> {
48 unsafe { &*self.val.get() }.as_ref()
49 }
50
51 #[inline(always)]
53 pub fn get_static_unchecked(&self) -> &T {
54 self.get_static().unwrap_or_else(|| {
55 unreachable!("StaticType not set value, Please is use static_val.init()")
56 })
57 }
58
59 #[inline(always)]
61 pub fn get_mut(&self) -> &mut Option<T> {
62 unsafe { &mut *self.val.get() }
63 }
64
65 #[inline(always)]
66 pub fn get_safe(&self) -> Option<&T> {
67 if !*self.is_init_lock.lock() {
68 return None;
69 }
70 unsafe { &*self.val.get() }.as_ref()
71 }
72
73 pub fn force_drop(&self) -> Option<T> {
76 *self.is_init_lock.lock() = false;
77 self.get_mut().take()
78 }
79}
80
81impl<T, F> Deref for StaticTypeForStd<T, F> {
82 type Target = T;
83 fn deref(&self) -> &Self::Target {
84 self.get_static_unchecked()
85 }
86}
87
88impl<T, F: FnOnce() -> T> DerefMut for StaticTypeForStd<T, F> {
90 fn deref_mut(&mut self) -> &mut Self::Target {
91 self.get_mut()
92 .as_mut()
93 .unwrap_or_else(|| unreachable!("StaticType not set"))
94 }
95}
96
97impl<T, F> AsRef<T> for StaticTypeForStd<T, F> {
98 fn as_ref(&self) -> &T {
99 self.get_static_unchecked()
100 }
101}
102
103unsafe impl<T, F> Send for StaticTypeForStd<T, F> {}
106unsafe impl<T, F> Sync for StaticTypeForStd<T, F> {}
107
108impl<T: Debug, F: FnOnce() -> T> Debug for StaticTypeForStd<T, F> {
109 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
110 let val = self.get_static_unchecked();
111 f.write_fmt(format_args!("{val:?}"))
112 }
113}
114
115impl<T: Display, F> Display for StaticTypeForStd<T, F> {
116 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
117 let val = self.get_static().map(|x| format!("{x}"));
118 let val = val.unwrap_or_else(|| "None".to_string());
119 f.write_str(&val)
120 }
121}
122
123#[test]
124fn test_static_type() {
125 static STATIC_TYPE: StaticTypeForStd<i32> = StaticTypeForStd::new(|| {
127 let r = 11 + 11;
128 println!("init_fun: {}", r);
129 r
130 });
131
132 assert_eq!(format!("{}", STATIC_TYPE), "None");
134
135 assert_eq!(STATIC_TYPE.is_init(), false);
137 STATIC_TYPE.init_static();
141
142 STATIC_TYPE.init_static();
144
145 assert_eq!(format!("{}", STATIC_TYPE), "22");
147
148 assert_eq!(*STATIC_TYPE, 22);
150}