1use std::{
2 cell::UnsafeCell,
3 fmt::{Debug, Display},
4 ops::{Deref, DerefMut},
5};
6
7pub struct StaticType<T> {
10 val: UnsafeCell<Option<T>>,
11 init_lock: spin::Mutex<bool>,
12}
13
14impl<T> StaticType<T> {
15 #[must_use]
18 pub const fn new() -> Self {
19 Self {
20 val: UnsafeCell::new(None),
21 init_lock: spin::Mutex::new(false),
22 }
23 }
24 #[must_use]
27 pub fn is_init(&self) -> bool {
28 *self.init_lock.lock()
29 }
30
31 #[inline(always)]
35 fn init(&self, val: T) {
36 *self.get_mut() = Some(val);
37 }
38
39 #[inline(always)]
42 pub fn init_call<F: FnOnce() -> T>(&self, call: F) {
43 let mut lock = self.init_lock.lock();
44 if !*lock {
45 *lock = true;
46 self.init(call());
47 }
48 }
49
50 #[inline(always)]
53 pub fn get_or_init<F: FnOnce() -> T>(&self, call: F) -> &T {
54 self.init_call(call);
55 self.get_static_unchecked()
56 }
57
58 #[inline(always)]
62 pub fn get_static(&self) -> Option<&T> {
63 unsafe { &*self.val.get() }.as_ref()
64 }
65
66 #[inline(always)]
70 pub fn get_static_unchecked(&self) -> &T {
71 self.get_static()
72 .unwrap_or_else(|| unreachable!("StaticType not set value, Please is call static_val.init_call(|| you init code )"))
73 }
74
75 #[inline(always)]
79 pub fn get_mut(&self) -> &mut Option<T> {
80 unsafe { &mut *self.val.get() }
81 }
82
83 #[inline(always)]
86 pub fn get_safe(&self) -> Option<&T> {
87 if !*self.init_lock.lock() {
88 return None;
89 }
90 unsafe { &*self.val.get() }.as_ref()
91 }
92
93 pub fn force_drop(&self) -> Option<T> {
98 *self.init_lock.lock() = false;
99 self.get_mut().take()
100 }
101}
102
103impl<T> Deref for StaticType<T> {
104 type Target = T;
105 fn deref(&self) -> &Self::Target {
106 self.get_static_unchecked()
107 }
108}
109
110impl<T> DerefMut for StaticType<T> {
112 fn deref_mut(&mut self) -> &mut Self::Target {
113 self.get_mut()
114 .as_mut()
115 .unwrap_or_else(|| unreachable!("StaticType not set"))
116 }
117}
118
119impl<T> AsRef<T> for StaticType<T> {
120 fn as_ref(&self) -> &T {
121 self.get_static_unchecked()
122 }
123}
124
125unsafe impl<T> Send for StaticType<T> {}
128unsafe impl<T> Sync for StaticType<T> {}
129
130impl<T: Default> Default for StaticType<T> {
131 fn default() -> Self {
132 Self {
133 val: Default::default(),
134 init_lock: Default::default(),
135 }
136 }
137}
138
139impl<T: Debug> Debug for StaticType<T> {
140 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
141 let val = self.get_static_unchecked();
142 f.write_fmt(format_args!("{val:?}"))
143 }
144}
145
146impl<T: Display> Display for StaticType<T> {
147 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
148 let val = self.get_static().map(|x| format!("{x}"));
149 let val = val.unwrap_or_else(|| "None".to_string());
150 f.write_str(&val)
151 }
152}
153
154#[test]
155fn test_static_type() {
156 static STATIC_TYPE: StaticType<i32> = StaticType::new();
158
159 assert_eq!(format!("{}", STATIC_TYPE), "None");
161
162 STATIC_TYPE.init_call(|| 22);
164
165 STATIC_TYPE.init_call(|| 33);
167
168 assert_eq!(format!("{}", STATIC_TYPE), "22");
170
171 assert_eq!(*STATIC_TYPE, 22);
173}