1use core::ffi::c_void;
2use alloc::sync::Arc;
3
4use crate::nullable::{null, Nullable};
5
6#[derive(Debug)]
7#[repr(transparent)]
8pub struct ArcPtr<T: ?Sized>(*const T);
9
10impl<T> ArcPtr<T> {
11 pub fn new(item: T) -> ArcPtr<T> {
12 ArcPtr::from(Arc::new(item))
13 }
14}
15
16impl<T: ?Sized> ArcPtr<T> {
17 #[doc(hidden)]
18 pub(crate) fn as_ptr(&self) -> *const T {
19 self.0
20 }
21
22 pub fn is_null(&self) -> bool {
23 self.0.is_null()
24 }
25
26 pub fn as_ref(&self) -> Option<&T> {
27 if self.is_null() {
28 None
29 } else {
30 Some(unsafe { &*self.0 })
31 }
32 }
33
34 pub fn into_arc(self) -> Arc<T> {
35 unsafe { Arc::from_raw(self.0 as *mut T) }
36 }
37}
38
39impl<T: ?Sized> core::ops::Deref for ArcPtr<T> {
40 type Target = T;
41
42 fn deref(&self) -> &Self::Target {
43 unsafe { &*self.0 }
44 }
45}
46
47impl<T: ?Sized> Clone for ArcPtr<T> {
48 fn clone(&self) -> ArcPtr<T> {
49 let arc = unsafe { Arc::from_raw(self.0) };
50 let arc1 = Arc::clone(&arc);
51 core::mem::forget(arc);
52 ArcPtr(Arc::into_raw(arc1))
53 }
54}
55
56impl<T: ?Sized> Drop for ArcPtr<T> {
57 fn drop(&mut self) {
58 unsafe { Arc::from_raw(self.0 as *mut c_void) };
59 }
60}
61
62impl<T: ?Sized> From<Arc<T>> for ArcPtr<T> {
63 fn from(arc: Arc<T>) -> ArcPtr<T> {
64 ArcPtr(Arc::into_raw(arc))
65 }
66}
67
68pub fn nullable_arc<T>(thing: T) -> Nullable<ArcPtr<T>> {
69 Nullable::from(ArcPtr::new(thing))
70}
71
72#[no_mangle]
73pub extern "C" fn arc_clone(arc: ArcPtr<c_void>) -> Nullable<ArcPtr<c_void>> {
74 match arc.is_null() {
75 true => null(),
76 false => Nullable::from(arc.clone()),
77 }
78}
79
80#[no_mangle]
81pub extern "C" fn arc_drop(arc: ArcPtr<c_void>) -> bool {
82 match arc.is_null() {
83 true => false,
84 false => {
85 arc.into_arc();
86 true
87 }
88 }
89}