rust Rc&lt;[T]&gt; try_unwrap到Vec中< T>

2g32fytz  于 12个月前  发布在  其他
关注(0)|答案(1)|浏览(174)

有没有像try_unwrap这样的函数可以让我从Rc中获取一个切片?或者我必须手动检查引用计数并使用不安全的指针魔法来实现这一点?
编辑:它看起来像没有这样的事情.我也不能只是提取指针和调用forget,因为这将泄漏计数器.在这种情况下我应该怎么办?

ilmyapht

ilmyapht1#

没有内置函数,但可以使用下面的代码:

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.cast::<T>(),
            v.spare_capacity_mut().as_mut_ptr() as *mut T, // ≙ MaybeUninit::slice_as_mut_ptr
            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)
}

字符串
Playground

相关问题