rc_borrow/
lib.rs

1// NB: Last updated for Rust 1.40 parity. All impls are in rustdoc gutter order.
2
3//! Borrowed forms of [`Rc`] and [`Arc`].
4//!
5//! [`ArcBorrow<_>`](`ArcBorrow`) is functionally equivalent to `&Arc<_>`,
6//! but it's represented as `&T`, avoiding the extra indirection.
7//!
8//! # Examples
9//!
10//! ```rust
11//! # use {rc_borrow::*, std::sync::Arc};
12//! # type Resource = u32;
13//! # fn acquire_resource() -> Arc<u32> { Arc::new(0) }
14//! let resource: Arc<Resource> = acquire_resource();
15//! let borrowed: ArcBorrow<'_, Resource> = (&resource).into();
16//! let reference: &Resource = ArcBorrow::downgrade(borrowed);
17//! let cloned: Arc<Resource> = ArcBorrow::upgrade(borrowed);
18//! fn use_resource(resource: &Resource) { /* ... */ }
19//! use_resource(&borrowed);
20//! ```
21
22#![warn(missing_docs, missing_debug_implementations)]
23#![no_std]
24
25extern crate alloc;
26#[cfg(feature = "std")]
27extern crate std;
28
29#[cfg(feature = "erasable")]
30use erasable::{Erasable, ErasablePtr, ErasedPtr};
31#[cfg(feature = "std")]
32use std::{
33    io,
34    net::ToSocketAddrs,
35    panic::{RefUnwindSafe, UnwindSafe},
36};
37use {
38    alloc::{
39        rc::{self, Rc},
40        sync::{self, Arc},
41    },
42    core::{
43        borrow::Borrow,
44        cmp::Ordering,
45        fmt::{
46            self, Binary, Debug, Display, Formatter, LowerExp, LowerHex, Octal, Pointer, UpperExp,
47            UpperHex,
48        },
49        hash::{Hash, Hasher},
50        marker::PhantomData,
51        mem::ManuallyDrop,
52        ops::Deref,
53        ptr,
54    },
55};
56
57/// This trait is a polyfill for (`A`)`Rc::as_raw` and (`A`)`Rc::clone_raw`.
58/// See https://internals.rust-lang.org/t/_/11463/11 for why these are important.
59/// By using a trait here, we can more easily switch when these functions are available.
60trait RawRc<T: ?Sized> {
61    type Weak;
62
63    //noinspection RsSelfConvention
64    fn as_raw(this: &Self) -> *const T;
65
66    /// # Safety
67    ///
68    /// This pointer must have come from [`RawRc::as_raw`] or `into_raw`.
69    unsafe fn clone_raw(this: *const T) -> Self;
70
71    unsafe fn downgrade_raw(this: *const T) -> Self::Weak;
72}
73
74impl<T: ?Sized> RawRc<T> for Arc<T> {
75    type Weak = sync::Weak<T>;
76
77    #[inline(always)]
78    fn as_raw(this: &Self) -> *const T {
79        // Arc::as_ptr(this)
80        Arc::into_raw(unsafe { ptr::read(this) })
81    }
82
83    #[inline(always)]
84    unsafe fn clone_raw(this: *const T) -> Self {
85        Arc::clone(&ManuallyDrop::new(Arc::from_raw(this)))
86    }
87
88    #[inline(always)]
89    unsafe fn downgrade_raw(this: *const T) -> sync::Weak<T> {
90        let this = ManuallyDrop::new(Arc::from_raw(this));
91        Arc::downgrade(&this)
92    }
93}
94
95impl<T: ?Sized> RawRc<T> for Rc<T> {
96    type Weak = rc::Weak<T>;
97
98    #[inline(always)]
99    fn as_raw(this: &Self) -> *const T {
100        // Rc::as_ptr(this)
101        Rc::into_raw(unsafe { ptr::read(this) })
102    }
103
104    #[inline(always)]
105    unsafe fn clone_raw(this: *const T) -> Self {
106        Rc::clone(&ManuallyDrop::new(Rc::from_raw(this)))
107    }
108
109    #[inline(always)]
110    unsafe fn downgrade_raw(this: *const T) -> rc::Weak<T> {
111        let this = ManuallyDrop::new(Rc::from_raw(this));
112        Rc::downgrade(&this)
113    }
114}
115
116// sigh, I almost got away without this...
117macro_rules! doc_comment {
118    ($doc:expr, $($tt:tt)*) => {
119        #[doc = $doc]
120        $($tt)*
121    };
122}
123
124macro_rules! rc_borrow {
125    ($($(#[$m:meta])* $vis:vis struct $RcBorrow:ident = &$rc:ident::$Rc:ident;)*) => {$(
126        $(#[$m])*
127        $vis struct $RcBorrow<'a, T: ?Sized> {
128            raw: ptr::NonNull<T>,
129            marker: PhantomData<&'a $Rc<T>>
130        }
131
132        // NB: these cannot be `where &T: Send/Sync` as they allow upgrading to $Rc.
133        unsafe impl<'a, T: ?Sized> Send for $RcBorrow<'a, T> where &'a $Rc<T>: Send {}
134        unsafe impl<'a, T: ?Sized> Sync for $RcBorrow<'a, T> where &'a $Rc<T>: Sync {}
135
136        impl<'a, T: ?Sized> From<&'a $Rc<T>> for $RcBorrow<'a, T> {
137            fn from(v: &'a $Rc<T>) -> $RcBorrow<'a, T> {
138                let raw = <$Rc<T> as RawRc<T>>::as_raw(v);
139                $RcBorrow {
140                    raw: unsafe { ptr::NonNull::new_unchecked(raw as *mut T) },
141                    marker: PhantomData,
142                }
143            }
144        }
145
146        impl<'a, T: ?Sized> $RcBorrow<'a, T> {
147            /// Convert this borrowed pointer into an owned pointer.
148            $vis fn upgrade(this: Self) -> $Rc<T> {
149                unsafe { <$Rc<T> as RawRc<T>>::clone_raw(this.raw.as_ptr()) }
150            }
151
152            /// Convert this borrowed pointer into a weak pointer.
153            $vis fn to_weak(this: Self) -> $rc::Weak<T> {
154                unsafe { <$Rc<T> as RawRc<T>>::downgrade_raw(this.raw.as_ptr()) }
155            }
156
157            /// Convert this borrowed pointer into a standard reference.
158            ///
159            /// This gives you a long-lived reference,
160            /// whereas dereferencing gives a temporary borrow.
161            $vis fn downgrade(this: Self) -> &'a T {
162                unsafe { &*this.raw.as_ptr() }
163            }
164
165            /// Get the number of strong owning pointers to this allocation.
166            $vis fn strong_count(this: Self) -> usize {
167                let rc = unsafe { ManuallyDrop::new($Rc::from_raw(Self::into_raw(this))) };
168                $Rc::strong_count(&rc)
169            }
170
171            /// Get the number of weak owning pointers to this allocation.
172            $vis fn weak_count(this: Self) -> usize {
173                let rc = unsafe { ManuallyDrop::new($Rc::from_raw(Self::into_raw(this))) };
174                $Rc::weak_count(&rc)
175            }
176
177            /// Get a raw pointer that can be used with `from_raw`.
178            $vis fn into_raw(this: Self) -> *const T {
179                ManuallyDrop::new(this).raw.as_ptr()
180            }
181
182            doc_comment! {
183                concat!("\
184Construct a new `", stringify!($RcBorrow), "` from a raw pointer.
185
186# Safety
187
188The raw pointer must have been previously returned by a call to
189`",stringify!($RcBorrow),"<U>::into_raw` or `",stringify!($Rc),"<U>::as_raw`
190where `U` must have the same size and alignment as `T`. This is trivially true
191if `U` is `T`. Note that if `U` is not `T`, this is a pointer cast (transmute)
192between the two types, and the types must be transmute-compatible."),
193                $vis unsafe fn from_raw(ptr: *const T) -> Self {
194                    $RcBorrow {
195                        raw: ptr::NonNull::new_unchecked(ptr as *mut T),
196                        marker: PhantomData
197                    }
198                }
199            }
200        }
201
202        // ~~~ &T like impls ~~~ //
203
204        #[cfg(feature = "erasable")]
205        unsafe impl<T: ?Sized> ErasablePtr for $RcBorrow<'_, T>
206        where
207            T: Erasable
208        {
209            #[inline(always)]
210            fn erase(this: Self) -> ErasedPtr {
211                T::erase(this.raw)
212            }
213
214            #[inline(always)]
215            unsafe fn unerase(this: ErasedPtr) -> Self {
216                $RcBorrow {
217                    raw: T::unerase(this),
218                    marker: PhantomData,
219                }
220            }
221        }
222
223        impl<T: ?Sized, U: ?Sized> AsRef<U> for $RcBorrow<'_, T>
224        where
225            T: AsRef<U>,
226        {
227            fn as_ref(&self) -> &U {
228                (**self).as_ref()
229            }
230        }
231
232        impl<T: ?Sized> Binary for $RcBorrow<'_, T>
233        where
234            T: Binary,
235        {
236            fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
237                (**self).fmt(f)
238            }
239        }
240
241        impl<T: ?Sized> Borrow<T> for $RcBorrow<'_, T> {
242            fn borrow(&self) -> &T {
243                &**self
244            }
245        }
246
247        impl<T: ?Sized> Clone for $RcBorrow<'_, T> {
248            fn clone(&self) -> Self { *self }
249        }
250
251        // CoerceUnsized is unstable
252
253        impl<T: ?Sized> Copy for $RcBorrow<'_, T> {}
254
255        impl<T: ?Sized> Debug for $RcBorrow<'_, T>
256        where
257            T: Debug
258        {
259            fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
260                (**self).fmt(f)
261            }
262        }
263
264        impl<T: ?Sized> Deref for $RcBorrow<'_, T> {
265            type Target = T;
266            fn deref(&self) -> &T {
267                Self::downgrade(*self)
268            }
269        }
270
271        // DispatchFromDyn is unstable
272
273        impl<T: ?Sized> Display for $RcBorrow<'_, T>
274        where
275            T: Display,
276        {
277            fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
278                (**self).fmt(f)
279            }
280        }
281
282        impl<T: ?Sized> Eq for $RcBorrow<'_, T> where T: Eq {}
283
284        // Fn, FnMut, FnOnce are unstable to implement
285
286        impl<T: ?Sized> Hash for $RcBorrow<'_, T>
287        where
288            T: Hash,
289        {
290            fn hash<H: Hasher>(&self, state: &mut H) {
291                (**self).hash(state)
292            }
293        }
294
295        impl<T: ?Sized> LowerExp for $RcBorrow<'_, T>
296        where
297            T: LowerExp,
298        {
299            fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
300                (**self).fmt(f)
301            }
302        }
303
304        impl<T: ?Sized> LowerHex for $RcBorrow<'_, T>
305        where
306            T: LowerHex,
307        {
308            fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
309                (**self).fmt(f)
310            }
311        }
312
313        impl<T: ?Sized> Octal for $RcBorrow<'_, T>
314        where
315            T: Octal,
316        {
317            fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
318                (**self).fmt(f)
319            }
320        }
321
322        impl<T: Ord> Ord for $RcBorrow<'_, T>
323        where
324            T: Ord,
325        {
326            fn cmp(&self, other: &Self) -> Ordering {
327                (**self).cmp(&**other)
328            }
329        }
330
331        impl<T: ?Sized, O> PartialEq<O> for $RcBorrow<'_, T>
332        where
333            O: Deref,
334            T: PartialEq<O::Target>,
335        {
336            fn eq(&self, other: &O) -> bool {
337                (**self).eq(&*other)
338            }
339        }
340
341        impl<T: ?Sized, O> PartialOrd<O> for $RcBorrow<'_, T>
342        where
343            O: Deref,
344            T: PartialOrd<O::Target>,
345        {
346            fn partial_cmp(&self, other: &O) -> Option<Ordering> {
347                (**self).partial_cmp(&*other)
348            }
349        }
350
351        impl<T: ?Sized> Pointer for $RcBorrow<'_, T>
352        where
353            T: Pointer,
354        {
355            fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
356                (**self).fmt(f)
357            }
358        }
359
360        #[cfg(feature = "std")]
361        impl<T: ?Sized> ToSocketAddrs for $RcBorrow<'_, T>
362        where
363            T: ToSocketAddrs
364        {
365            type Iter = T::Iter;
366            fn to_socket_addrs(&self) -> io::Result<T::Iter> {
367                (**self).to_socket_addrs()
368            }
369        }
370
371        impl<T: ?Sized> Unpin for $RcBorrow<'_, T> {}
372
373        #[cfg(feature = "std")]
374        impl<T: ?Sized> UnwindSafe for $RcBorrow<'_, T> where T: RefUnwindSafe {}
375
376        impl<T: ?Sized> UpperExp for $RcBorrow<'_, T>
377        where
378            T: UpperExp,
379        {
380            fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
381                (**self).fmt(f)
382            }
383        }
384
385        impl<T: ?Sized> UpperHex for $RcBorrow<'_, T>
386        where
387            T: UpperHex,
388        {
389            fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
390                (**self).fmt(f)
391            }
392        }
393    )*}
394}
395
396rc_borrow! {
397    /// Borrowed version of [`Arc`].
398    ///
399    /// This type is guaranteed to have the same repr as `&T`.
400    #[repr(transparent)]
401    pub struct ArcBorrow = &sync::Arc;
402    /// Borrowed version of [`Rc`].
403    ///
404    /// This type is guaranteed to have the same repr as `&T`.
405    #[repr(transparent)]
406    pub struct RcBorrow = &rc::Rc;
407}