1#![no_std]
2#![deny(
3 warnings,
4 missing_docs,
5 missing_debug_implementations,
6 rustdoc::broken_intra_doc_links,
7 clippy::all,
8 clippy::pedantic
9)]
10#![doc = include_str!("../Readme.md")]
11
12use core::{
13 cell::UnsafeCell,
14 default::Default,
15 fmt::{Binary, Debug, Display, LowerExp, LowerHex, Octal, Pointer, UpperExp, UpperHex},
16 ops::{Deref, DerefMut, IndexMut},
17};
18
19pub struct NearSafeCell<T>(UnsafeCell<T>);
26
27impl<T: Default> Default for NearSafeCell<T> {
28 fn default() -> Self {
29 Self::new(T::default())
30 }
31}
32
33impl<T> NearSafeCell<T> {
34 pub const fn new(val: T) -> Self {
36 Self(UnsafeCell::new(val))
37 }
38 pub fn unwrap(self) -> T {
40 self.0.into_inner()
41 }
42 pub unsafe fn get_mut_unsafe(&self) -> &mut T {
46 &mut *self.get_mut_ptr()
47 }
48 pub unsafe fn index_mut_unchecked<Idx>(&self, idx: Idx) -> &mut T::Output
54 where
55 T: IndexMut<Idx>,
56 {
57 (*self.get_mut_ptr()).index_mut(idx)
58 }
59 pub fn get(&self) -> &T {
61 unsafe { &*self.get_ptr() }
63 }
64 pub fn get_mut(&mut self) -> &mut T {
66 self.0.get_mut()
67 }
68 pub const fn get_ptr(&self) -> *const T {
70 self.0.get()
71 }
72 pub const fn get_mut_ptr(&self) -> *mut T {
74 self.0.get()
75 }
76}
77
78unsafe impl<T: Sync> Sync for NearSafeCell<T> {}
83
84#[cfg(feature = "std")]
89use std::panic::RefUnwindSafe;
90#[cfg(feature = "std")]
91unsafe impl<T: RefUnwindSafe> RefUnwindSafe for NearSafeCell<T> {}
92
93impl<T> AsRef<T> for NearSafeCell<T> {
94 fn as_ref(&self) -> &T {
95 self.get()
96 }
97}
98impl<T> AsMut<T> for NearSafeCell<T> {
99 fn as_mut(&mut self) -> &mut T {
100 self.get_mut()
101 }
102}
103
104impl<T> Deref for NearSafeCell<T> {
105 type Target = T;
106 fn deref(&self) -> &Self::Target {
107 self.get()
108 }
109}
110impl<T> DerefMut for NearSafeCell<T> {
111 fn deref_mut(&mut self) -> &mut Self::Target {
112 self.get_mut()
113 }
114}
115
116impl<T: Debug> Debug for NearSafeCell<T> {
117 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
118 f.debug_tuple("NearSafeCell").field(self.get()).finish()
119 }
120}
121
122impl<T: Display> Display for NearSafeCell<T> {
123 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
124 self.get().fmt(f)
125 }
126}
127impl<T: Octal> Octal for NearSafeCell<T> {
128 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
129 self.get().fmt(f)
130 }
131}
132impl<T: LowerHex> LowerHex for NearSafeCell<T> {
133 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
134 self.get().fmt(f)
135 }
136}
137impl<T: UpperHex> UpperHex for NearSafeCell<T> {
138 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
139 self.get().fmt(f)
140 }
141}
142impl<T: Pointer> Pointer for NearSafeCell<T> {
143 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
144 self.get().fmt(f)
145 }
146}
147impl<T: Binary> Binary for NearSafeCell<T> {
148 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
149 self.get().fmt(f)
150 }
151}
152impl<T: LowerExp> LowerExp for NearSafeCell<T> {
153 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
154 self.get().fmt(f)
155 }
156}
157impl<T: UpperExp> UpperExp for NearSafeCell<T> {
158 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
159 self.get().fmt(f)
160 }
161}
162
163#[cfg(test)]
164mod tests {
165 use super::*;
166 use core::ops::{Deref, DerefMut};
167
168 #[test]
169 fn usage() {
170 let mut cell = NearSafeCell::<usize>::default();
171 assert_eq!(cell.get(), &usize::default());
172 cell = NearSafeCell::new(24);
173
174 assert_eq!(cell.get_ptr(), cell.get() as *const _);
175 assert_eq!(cell.get_mut_ptr(), cell.get_mut() as *mut _);
176
177 assert_eq!(cell.as_ref(), &24);
178 assert_eq!(cell.as_mut(), &mut 24);
179 assert_eq!(cell.deref(), &24);
180 assert_eq!(cell.deref_mut(), &mut 24);
181
182 let interiorly_mutable = unsafe { cell.get_mut_unsafe() };
183 assert_eq!(interiorly_mutable, &mut 24);
184 *interiorly_mutable = 42;
185 drop(interiorly_mutable);
186
187 let shared = cell.get();
188 let shared2 = cell.get();
189 assert_eq!(shared, &42);
190 assert_eq!(shared, shared2);
191
192 let mutable = cell.get_mut();
193 assert_eq!(mutable, &mut 42);
194 *mutable = 242;
195
196 assert_eq!(cell.unwrap(), 242);
197 }
198
199 #[test]
200 fn indexing() {
201 use core::ops::Index;
202 let cell = NearSafeCell::new([1, 2, 3, 4, 5]);
203 {
204 let sub_0 = cell.index(2..);
205 let sub_1 = unsafe { cell.index_mut_unchecked(..2) };
206 assert_eq!(sub_0, [3, 4, 5]);
207 assert_eq!(sub_1, [1, 2]);
208 sub_1.copy_from_slice(&[24, 42]);
209 assert_eq!(sub_0, [3, 4, 5]);
210 assert_eq!(sub_1, [24, 42]);
211 }
212 assert_eq!(cell.unwrap(), [24, 42, 3, 4, 5]);
213 }
214
215 include!("test_utilities.rs");
216 #[test]
217 fn formatting() {
218 let mut buffer = [0u8; 32];
219 let cell = NearSafeCell::new(42);
220 assert_eq!(
221 format(&mut buffer, format_args!("{:?}", cell)).unwrap(),
222 "NearSafeCell(42)"
223 );
224 assert_eq!(format(&mut buffer, format_args!("{}", cell)).unwrap(), "42");
225 assert_eq!(
226 format(&mut buffer, format_args!("{:o}", cell)).unwrap(),
227 "52"
228 );
229 assert_eq!(
230 format(&mut buffer, format_args!("{:x}", cell)).unwrap(),
231 "2a"
232 );
233 assert_eq!(
234 format(&mut buffer, format_args!("{:X}", cell)).unwrap(),
235 "2A"
236 );
237 assert_eq!(
238 format(&mut buffer, format_args!("{:b}", cell)).unwrap(),
239 "101010"
240 );
241 assert_eq!(
242 format(&mut buffer, format_args!("{:e}", cell)).unwrap(),
243 "4.2e1"
244 );
245 assert_eq!(
246 format(&mut buffer, format_args!("{:E}", cell)).unwrap(),
247 "4.2E1"
248 );
249 let cell = NearSafeCell::new(42 as *const u8);
250 assert_eq!(
251 format(&mut buffer, format_args!("{:p}", cell)).unwrap(),
252 "0x2a"
253 );
254 }
255}