refs/
rglica.rs

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
13/// `Rglica` is a thin wrapper around a raw, non-owning pointer (`NonNull<T>`).
14///
15/// This struct provides C++ style raw pointer behavior in Rust.
16///
17/// # Safety
18/// - Not safe at all.
19///
20/// # Notes
21/// - Use with caution — misuse can cause undefined behavior.
22/// - Designed for performance-sensitive code.
23///
24/// Very unsafe — avoid using unless absolutely necessary.
25pub 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            // backtrace();
80            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            // backtrace();
91            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}