是否有像
try_unwrap
这样的函数可以让我从 Rc
获取切片?
或者我是否必须手动检查引用计数并使用不安全的指针魔术来实现此目的?
编辑:看起来没有这样的事情。我也不能只提取指针和调用
forget
因为这会泄漏计数器。这种情况我该怎么办?
没有内置函数,但您可以使用以下代码:
fn rc_slice_to_vec<T>(rc: Rc<[T]>) -> Result<Vec<T>, Rc<[T]>> {
use std::mem::ManuallyDrop;
if Rc::strong_count(&rc) != 1 {
return Err(rc);
}
let len = rc.len();
let mut v = Vec::with_capacity(len);
let rc_raw = Rc::into_raw(rc);
unsafe {
// SAFETY:
// * rc_raw is trivially valid for a read of `len * size_of::<T>()`
// * the pointer derived from `v` is trivially valid for a write of
// the same number of bytes
// * both pointers are properly aligned, they're derived from types
// that can hold `T`
// * the regions are from different allocations so they can't overlap
std::ptr::copy_nonoverlapping(
rc_raw as *const T,
v.spare_capacity_mut() as *mut _ as *mut T,
len
);
// SAFETY:
// * `len` is the capacity we requested so it's <= capacity
// * we've initialized the elements 0..len
v.set_len(len);
// SAFETY:
// * `ManuallyDrop<T>` has the same size and alignment as `T`
// * `rc_raw` is derived from `rc` which is a `Rc`
// * elements are wrapped in `ManuallyDrop` so `T`s `Drop` implementation
// is not invoked (we've moved the elements to `v`)
Rc::decrement_strong_count(rc_raw as *const [ManuallyDrop<T>]);
}
Ok(v)
}