1use core::ptr::from_ref;
2use std::{
3 any::type_name,
4 fmt::{Debug, Formatter},
5 ops::{Deref, DerefMut},
6 ptr::NonNull,
7};
8
9use log::error;
10
11use crate::Address;
12
13pub struct Rglica<T: ?Sized> {
26 pub ptr: Option<NonNull<T>>,
27}
28
29unsafe impl<T: ?Sized> Send for Rglica<T> {}
30unsafe impl<T: ?Sized> Sync for Rglica<T> {}
31
32impl<T: ?Sized> Copy for Rglica<T> {}
33
34impl<T: ?Sized> Clone for Rglica<T> {
35 fn clone(&self) -> Rglica<T> {
36 *self
37 }
38}
39
40impl<T: ?Sized> Rglica<T> {
41 pub const fn const_default() -> Self {
42 Self { ptr: None }
43 }
44
45 pub fn from_ref(rf: &T) -> Rglica<T> {
46 let ptr = NonNull::new((from_ref::<T>(rf)).cast_mut());
47 debug_assert!(ptr.is_some(), "Failed to cast ref to Rglica");
48 Self {
49 ptr: ptr.unwrap().into(),
50 }
51 }
52
53 pub fn is_null(&self) -> bool {
54 self.ptr.is_none()
55 }
56
57 pub fn is_ok(&self) -> bool {
58 self.ptr.is_some()
59 }
60
61 pub fn as_ptr(&self) -> *mut T {
62 self.ptr.unwrap().as_ptr()
63 }
64
65 pub fn get(&mut self) -> Option<&mut T> {
66 if self.is_ok() {
67 self.deref_mut().into()
68 } else {
69 None
70 }
71 }
72}
73
74impl<T: ?Sized> Deref for Rglica<T> {
75 type Target = T;
76 fn deref(&self) -> &T {
77 if self.is_null() {
78 error!("Null Rglica: {}", std::any::type_name::<T>());
79 panic!("Null Rglica: {}", std::any::type_name::<T>());
81 }
82 unsafe { self.ptr.unwrap().as_ref() }
83 }
84}
85
86impl<T: ?Sized> DerefMut for Rglica<T> {
87 fn deref_mut(&mut self) -> &mut T {
88 if self.is_null() {
89 error!("Null Rglica: {}", std::any::type_name::<T>());
90 panic!("Null Rglica: {}", std::any::type_name::<T>());
92 }
93 unsafe { self.ptr.unwrap().as_mut() }
94 }
95}
96
97impl<T: ?Sized> Default for Rglica<T> {
98 fn default() -> Rglica<T> {
99 Self { ptr: None }
100 }
101}
102
103impl<T: ?Sized> Debug for Rglica<T> {
104 default fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
105 type_name::<T>().fmt(f)
106 }
107}
108
109impl<T: ?Sized + Debug> Debug for Rglica<T> {
110 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
111 if self.is_null() {
112 return self.ptr.fmt(f);
113 }
114 self.deref().fmt(f)
115 }
116}
117
118impl<T: ?Sized> Address for Rglica<T> {
119 fn address(&self) -> usize {
120 self.ptr.map_or(0, |ptr| ptr.as_ptr() as *const u8 as usize)
121 }
122}
123
124#[cfg(test)]
125mod test {
126 use std::ops::{Deref, DerefMut};
127
128 use crate::{Address, Rglica};
129
130 struct NoDebug;
131
132 #[test]
133 #[should_panic(expected = "Null Rglica: i32")]
134 fn null_rglica() {
135 let null = Rglica::<i32>::default();
136 assert!(null.is_null());
137 assert_eq!(null.is_ok(), false);
138 _ = null.deref();
139 }
140
141 #[test]
142 #[should_panic(expected = "Null Rglica: i32")]
143 fn null_rglica_mut() {
144 let mut null = Rglica::<i32>::default();
145 assert!(null.is_null());
146 assert_eq!(null.is_ok(), false);
147 _ = null.deref_mut();
148 }
149
150 #[test]
151 fn rglica_misc() {
152 let five = 5;
153
154 let five = &five;
155
156 let mut val = Rglica::from_ref(five);
157 assert_eq!(val.address(), five as *const i32 as usize);
158
159 assert_eq!(val.is_null(), false);
160 assert_eq!(val.is_ok(), true);
161
162 assert_eq!("5", &format!("{val:?}"));
163
164 let cloned = val.clone();
165
166 assert_eq!(val.deref(), cloned.deref());
167
168 let get = val.get().unwrap();
169
170 *get = 10;
171
172 assert_eq!(*val.deref(), 10);
173
174 assert_eq!(
175 "\"refs::rglica::test::NoDebug\"",
176 format!("{:?}", Rglica::from_ref(&NoDebug))
177 );
178
179 assert_eq!("None", format!("{:?}", Rglica::<i32>::default()));
180
181 assert_eq!(None, Rglica::<i32>::default().get());
182 }
183}