@@ -24,13 +24,13 @@ use crate::{
2424} ;
2525use alloc:: boxed:: Box ;
2626use core:: {
27- alloc:: AllocError ,
27+ alloc:: { AllocError , Layout } ,
2828 fmt,
2929 marker:: { PhantomData , Unsize } ,
3030 mem:: { ManuallyDrop , MaybeUninit } ,
3131 ops:: { Deref , DerefMut } ,
3232 pin:: Pin ,
33- ptr:: NonNull ,
33+ ptr:: { NonNull , Pointee } ,
3434} ;
3535use macros:: pin_data;
3636
@@ -215,6 +215,48 @@ impl<T: ?Sized> Arc<T> {
215215 }
216216 }
217217
218+ /// Convert the [`Arc`] into a raw pointer.
219+ ///
220+ /// The raw pointer has ownership of the refcount that this Arc object owned.
221+ pub fn into_raw ( self ) -> * const T {
222+ let ptr = self . ptr . as_ptr ( ) ;
223+ core:: mem:: forget ( self ) ;
224+ // SAFETY: The pointer is valid.
225+ unsafe { core:: ptr:: addr_of!( ( * ptr) . data) }
226+ }
227+
228+ /// Recreates an [`Arc`] instance previously deconstructed via [`Arc::into_raw`].
229+ ///
230+ /// # Safety
231+ ///
232+ /// `ptr` must have been returned by a previous call to [`Arc::into_raw`]. Additionally, it
233+ /// must not be called more than once for each previous call to [`Arc::into_raw`].
234+ pub unsafe fn from_raw ( ptr : * const T ) -> Self {
235+ let refcount_layout = Layout :: new :: < bindings:: refcount_t > ( ) ;
236+ // SAFETY: The caller guarantees that the pointer is valid.
237+ let val_layout = Layout :: for_value ( unsafe { & * ptr } ) ;
238+ // SAFETY: We're computing the layout of a real struct that existed when compiling this
239+ // binary, so its layout is not so large that it can trigger arithmetic overflow.
240+ let val_offset = unsafe { refcount_layout. extend ( val_layout) . unwrap_unchecked ( ) . 1 } ;
241+
242+ let metadata: <T as Pointee >:: Metadata = core:: ptr:: metadata ( ptr) ;
243+ // SAFETY: The metadata of `T` and `ArcInner<T>` is the same because `ArcInner` is a struct
244+ // with `T` as its last field.
245+ //
246+ // This is documented at:
247+ // <https://doc.rust-lang.org/std/ptr/trait.Pointee.html>.
248+ let metadata: <ArcInner < T > as Pointee >:: Metadata =
249+ unsafe { core:: mem:: transmute_copy ( & metadata) } ;
250+ // SAFETY: The pointer is in-bounds of an allocation both before and after offsetting the
251+ // pointer, since it originates from a previous call to `Arc::into_raw` and is still valid.
252+ let ptr = unsafe { ( ptr as * mut u8 ) . sub ( val_offset) as * mut ( ) } ;
253+ let ptr = core:: ptr:: from_raw_parts_mut ( ptr, metadata) ;
254+
255+ // SAFETY: By the safety requirements we know that `ptr` came from `Arc::into_raw`, so the
256+ // reference count held then will be owned by the new `Arc` object.
257+ unsafe { Self :: from_inner ( NonNull :: new_unchecked ( ptr) ) }
258+ }
259+
218260 /// Returns an [`ArcBorrow`] from the given [`Arc`].
219261 ///
220262 /// This is useful when the argument of a function call is an [`ArcBorrow`] (e.g., in a method
0 commit comments