1use core::ptr::from_mut;
2use std::{
3 fmt::{Debug, Formatter},
4 hash::{Hash, Hasher},
5 intrinsics::transmute_unchecked,
6 marker::Unsize,
7 ops::{CoerceUnsized, Deref, DerefMut},
8 ptr::{from_ref, null, null_mut},
9};
10
11use crate::{AsAny, Erased, RawPointer, Rglica, ToRglica, ref_counter::RefCounter, weak_from_ref};
12
13pub(crate) const PTR_SIZE: usize = size_of::<usize>();
14
15pub struct Weak<T: ?Sized = Erased> {
17 pub(crate) ptr: *mut T,
18 pub(crate) stamp: u64,
19 pub type_name: &'static str,
20}
21
22unsafe impl<T: ?Sized> Send for Weak<T> {}
23unsafe impl<T: ?Sized> Sync for Weak<T> {}
24
25impl<T: ?Sized> Copy for Weak<T> {}
26
27impl<T: ?Sized> Clone for Weak<T> {
28 fn clone(&self) -> Self {
29 *self
30 }
31}
32
33impl<T> Weak<T> {
34 pub const fn const_default() -> Self {
35 Self {
36 ptr: null_mut(),
37 stamp: 0,
38 type_name: std::any::type_name::<T>(),
39 }
40 }
41}
42
43impl<T: ?Sized> Weak<T> {
44 pub fn sized(&self) -> bool {
45 let ptr_size = size_of_val(&self.ptr);
46
47 if ptr_size == PTR_SIZE {
48 true
49 } else if ptr_size == PTR_SIZE * 2 {
50 false
51 } else {
52 unreachable!("Invalid ptr size: {ptr_size}")
53 }
54 }
55
56 pub(crate) fn addr(&self) -> usize {
57 if self.sized() {
58 self.ptr as *const u8 as usize
59 } else {
60 let ptr_bytes: [usize; 2] = unsafe { transmute_unchecked(self.ptr) };
62 ptr_bytes[0]
63 }
64 }
65
66 pub fn raw(&self) -> RawPointer {
67 RawPointer::new(self.addr(), self.stamp, self.type_name)
68 }
69
70 pub unsafe fn from_raw(ptr: RawPointer) -> Self {
71 let mut new = Weak::<T> {
72 stamp: ptr.stamp(),
73 type_name: ptr.type_name(),
74 ..Default::default()
75 };
76
77 let ptr = if new.sized() {
78 unsafe { transmute_unchecked(ptr.addr()) }
79 } else {
80 trait Trait {}
81 struct Struct;
82 impl Trait for Struct {}
83
84 let sized: *const Struct = null();
85 let un_sized: *const dyn Trait = sized;
86
87 let mut ptr_bytes: [usize; 2] = unsafe { transmute_unchecked(un_sized) };
88 ptr_bytes[0] = ptr.addr();
89 unsafe { transmute_unchecked(ptr_bytes) }
90 };
91
92 new.ptr = ptr;
93
94 new
95 }
96
97 pub fn was_initialized(&self) -> bool {
98 !self.ptr.is_null()
99 }
100
101 pub fn is_ok(&self) -> bool {
102 if self.ptr.is_null() {
103 return false;
104 }
105 let Some(stamp) = RefCounter::stamp_for_address(self.addr()) else {
106 return false;
107 };
108 if stamp != self.stamp {
109 return false;
110 }
111 true
112 }
113
114 pub fn is_null(&self) -> bool {
115 !self.is_ok()
116 }
117
118 pub fn get(&self) -> Option<&T> {
119 if self.is_ok() {
120 unsafe { self.deref_unchecked().into() }
121 } else {
122 None
123 }
124 }
125
126 pub fn get_mut(&mut self) -> Option<&mut T> {
127 if self.is_ok() {
128 unsafe { self.deref_unchecked_mut().into() }
129 } else {
130 None
131 }
132 }
133
134 pub unsafe fn deref_unchecked(&self) -> &T {
137 unsafe { self.ptr.as_ref().unwrap_unchecked() }
138 }
139
140 pub unsafe fn deref_unchecked_mut(&mut self) -> &mut T {
143 unsafe { self.ptr.as_mut().unwrap_unchecked() }
144 }
145
146 pub unsafe fn to_rglica(&self) -> Rglica<T> {
149 self.deref().to_rglica()
150 }
151
152 #[cfg(feature = "checks")]
153 fn check(&self, check_main: bool) {
154 use log::error;
155
156 assert!(
157 !check_main || hreads::is_main_thread(),
158 "Unsafe Weak pointer deref: {}. Thread is not Main. Thread id: {}",
159 self.type_name,
160 hreads::current_thread_id()
161 );
162
163 if self.ptr.is_null() {
164 error!("Defererencing never initialized weak pointer: {}", self.type_name,);
165 panic!("Defererencing never initialized weak pointer: {}", self.type_name,);
167 }
168
169 if self.is_null() {
170 #[cfg(feature = "pointers_info")]
171 let message = format!(
172 "Defererencing already freed weak pointer: {}. \nInfo: {}",
173 self.type_name,
174 crate::pointers_info::PointerInfo::get_info(self.addr())
175 );
176
177 #[cfg(not(feature = "pointers_info"))]
178 let message = format!("Defererencing already freed weak pointer: {}", self.type_name,);
179
180 error!("{message}");
181 panic!("{message}");
182 }
183 }
184
185 pub fn erase(&self) -> Weak {
186 Weak {
187 ptr: self.ptr.cast(),
188 stamp: self.stamp,
189 type_name: self.type_name,
190 }
191 }
192}
193
194impl<T> Weak<T> {
195 #[track_caller]
200 pub unsafe fn leak(val: T) -> Self {
201 let val = Box::new(val);
202 let address = from_ref::<T>(&val).cast::<u8>() as usize;
203 let ptr = from_mut::<T>(Box::leak(val));
204
205 assert_ne!(
206 address, 1,
207 "Invalid address. In could be a closure or empty type."
208 );
209
210 #[cfg(feature = "pointers_info")]
211 let stamp = RefCounter::add(address, std::panic::Location::caller());
212 #[cfg(not(feature = "pointers_info"))]
213 let stamp = RefCounter::add(address);
214
215 Self {
216 ptr,
217 stamp,
218 type_name: std::any::type_name::<T>(),
219 }
220 }
221}
222
223impl<T: ?Sized + AsAny> Weak<T> {
224 pub fn downcast<U: 'static>(&self) -> Option<Weak<U>> {
225 let rf = self.as_any().downcast_ref::<U>()?;
226 Some(weak_from_ref(rf))
227 }
228}
229
230impl<T: ?Sized> Deref for Weak<T> {
231 type Target = T;
232 fn deref(&self) -> &T {
233 #[cfg(feature = "checks")]
234 self.check(false);
235 unsafe { self.deref_unchecked() }
236 }
237}
238
239impl<T: ?Sized> DerefMut for Weak<T> {
240 fn deref_mut(&mut self) -> &mut T {
241 #[cfg(feature = "checks")]
242 self.check(true);
243 unsafe { self.deref_unchecked_mut() }
244 }
245}
246
247impl<T: ?Sized> Default for Weak<T> {
248 default fn default() -> Self {
249 trait Trait {}
250 struct Struct;
251 impl Trait for Struct {}
252
253 let sized: *const Struct = null();
254 let un_sized: *const dyn Trait = sized;
255
256 Self {
257 ptr: unsafe { transmute_unchecked(un_sized) },
258 stamp: 0,
259 type_name: "unsized null",
260 }
261 }
262}
263
264impl<T> Default for Weak<T> {
265 fn default() -> Self {
266 Self {
267 ptr: null_mut(),
268 stamp: 0,
269 type_name: std::any::type_name::<T>(),
270 }
271 }
272}
273
274impl<T> Eq for Weak<T> {}
275
276impl<T> PartialEq<Self> for Weak<T> {
277 fn eq(&self, other: &Self) -> bool {
278 self.ptr == other.ptr && self.stamp == other.stamp
279 }
280}
281
282impl<T> Hash for Weak<T> {
283 fn hash<H: Hasher>(&self, state: &mut H) {
284 self.ptr.hash(state);
285 self.stamp.hash(state);
286 }
287}
288
289impl<T: ?Sized + Debug> Debug for Weak<T> {
290 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
291 self.deref().fmt(f)
292 }
293}
294
295impl<T, U> CoerceUnsized<Weak<U>> for Weak<T>
296where
297 T: Unsize<U> + ?Sized,
298 U: ?Sized,
299{
300}