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