1use std::{
2 any::Any,
3 cell::Cell,
4 fmt::{Debug, Display, Formatter, Pointer},
5 ptr::NonNull,
6};
7
8pub struct Sc<T: ?Sized>(NonNull<ScBox<T>>);
13
14struct ScBox<T: ?Sized> {
15 ref_cnt: Cell<usize>,
16 value: T,
17}
18
19impl<T> Sc<T> {
20 #[inline]
30 pub fn new(value: T) -> Self {
31 Self::from_inner(Box::leak(Box::new(ScBox { ref_cnt: Cell::new(1), value })).into())
32 }
33
34 #[inline]
54 pub fn try_unwrap(this: Self) -> Result<T, Self> {
55 if Sc::ref_count(&this) == 1 {
56 unsafe {
57 let val = std::ptr::read(&*this); let layout = std::alloc::Layout::for_value(this.0.as_ref());
61 let ptr = this.0.as_ptr();
62 std::mem::forget(this);
63 std::alloc::dealloc(ptr as *mut _, layout);
64
65 Ok(val)
66 }
67 } else {
68 Err(this)
69 }
70 }
71}
72
73impl Sc<dyn Any> {
74 #[inline]
77 pub fn new_any<T: Any>(value: T) -> Self {
78 let inner: Box<ScBox<dyn Any>> = Box::new(ScBox { ref_cnt: Cell::new(1), value });
79 Self::from_inner(Box::leak(inner).into())
80 }
81}
82
83impl<T: ?Sized> Sc<T> {
84 #[inline]
97 pub fn ref_count(&self) -> usize { self.inner().ref_cnt() }
98
99 pub fn ptr_eq(this: &Self, other: &Self) -> bool {
116 std::ptr::addr_eq(this.0.as_ptr(), other.0.as_ptr())
117 }
118
119 fn from_inner(ptr: NonNull<ScBox<T>>) -> Self { Self(ptr) }
120
121 fn inner(&self) -> &ScBox<T> {
122 unsafe { self.0.as_ref() }
125 }
126}
127
128impl Sc<dyn Any> {
129 pub fn downcast<T: Any>(self) -> Result<Sc<T>, Sc<dyn Any>> {
149 if (*self).is::<T>() {
150 let ptr = self.0.cast::<ScBox<T>>();
151 std::mem::forget(self);
152 Ok(Sc::from_inner(ptr))
153 } else {
154 Err(self)
155 }
156 }
157}
158
159impl<T: ?Sized> ScBox<T> {
160 fn inc(&self) { self.ref_cnt.set(self.ref_cnt.get() + 1); }
161 fn dec(&self) { self.ref_cnt.set(self.ref_cnt.get() - 1) }
162 fn ref_cnt(&self) -> usize { self.ref_cnt.get() }
163}
164
165impl<T: ?Sized> std::ops::Deref for Sc<T> {
166 type Target = T;
167 #[inline]
168 fn deref(&self) -> &Self::Target { &self.inner().value }
169}
170
171impl<T: ?Sized> Drop for Sc<T> {
172 fn drop(&mut self) {
173 self.inner().dec();
174 if self.inner().ref_cnt() == 0 {
175 unsafe {
176 let layout = std::alloc::Layout::for_value(self.0.as_ref());
177 let ptr = self.0.as_ptr();
178 std::ptr::drop_in_place(ptr);
179 std::alloc::dealloc(ptr as *mut _, layout)
180 }
181 }
182 }
183}
184
185impl<T> Clone for Sc<T> {
186 #[inline]
187 fn clone(&self) -> Self {
188 self.inner().inc();
189 Self(self.0)
190 }
191}
192
193impl<T: ?Sized + Display> Display for Sc<T> {
194 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { Display::fmt(&**self, f) }
195}
196
197impl<T: ?Sized + Debug> Debug for Sc<T> {
198 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { Debug::fmt(&**self, f) }
199}
200
201impl<T: ?Sized> Pointer for Sc<T> {
202 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
203 Pointer::fmt(&(&**self as *const T), f)
204 }
205}
206
207impl<T: Default> Default for Sc<T> {
208 #[inline]
209 fn default() -> Sc<T> { Sc::new(Default::default()) }
210}
211
212impl<T: ?Sized + PartialEq> PartialEq for Sc<T> {
213 #[inline]
214 fn eq(&self, other: &Sc<T>) -> bool { **self == **other }
215}
216
217#[cfg(test)]
218mod tests {
219 use super::*;
220 #[test]
221 fn test_sc() {
222 let a = Sc::new(1);
223 assert_eq!(Sc::ref_count(&a), 1);
224 let b = Sc::clone(&a);
225 assert_eq!(Sc::ref_count(&b), 2);
226 drop(a);
227 assert_eq!(Sc::ref_count(&b), 1);
228 drop(b);
229 }
230}