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