@@ -24,13 +24,13 @@ use crate::{
24
24
} ;
25
25
use alloc:: boxed:: Box ;
26
26
use core:: {
27
- alloc:: AllocError ,
27
+ alloc:: { AllocError , Layout } ,
28
28
fmt,
29
29
marker:: { PhantomData , Unsize } ,
30
30
mem:: { ManuallyDrop , MaybeUninit } ,
31
31
ops:: { Deref , DerefMut } ,
32
32
pin:: Pin ,
33
- ptr:: NonNull ,
33
+ ptr:: { NonNull , Pointee } ,
34
34
} ;
35
35
use macros:: pin_data;
36
36
@@ -215,6 +215,48 @@ impl<T: ?Sized> Arc<T> {
215
215
}
216
216
}
217
217
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
+
218
260
/// Returns an [`ArcBorrow`] from the given [`Arc`].
219
261
///
220
262
/// This is useful when the argument of a function call is an [`ArcBorrow`] (e.g., in a method
0 commit comments