如何从&[u8]初始化一个Rc<RefCell<[u8]>>?

4
请注意,这个切片是没有大小限制的。我可以接受进行内存分配/复制,或者转移所有权。
我知道要创建一个简单的`Rc<[u8]>`,可以使用`Rc::from(Vec::into_boxed_slice(Vec::from(x)))`,但是这种方法在添加了`RefCell`后不起作用。我注意到`RefCell`允许`T: ?Sized`,但实际上很难构造一个包含无大小限制类型的RefCell。

2
如果你静态地知道长度,或者只有几种可能性,你可以通过数组并使用unsize coercion来处理。 - undefined
不需要经过Vec<u8>Box<[u8]>Rc<[u8]>直接实现了From<&[u8]> - undefined
1个回答

2

RefCell不像BoxRc那样使用间接引用,而是将其数据存储在堆栈上。这是RefCellUnsafeCell(都来自1.70.0版本)的简化定义。

pub struct RefCell<T: ?Sized> {
    borrow: Cell<BorrowFlag>,
    value: UnsafeCell<T>,
}

#[repr(transparent)]
pub struct UnsafeCell<T: ?Sized> {
    value: T,
}

RefCell可以持有不是Sized的T,但是它本身变成了!Sized。也许有一种使用不安全代码创建(some indirection) RefCell<[T]>的方法,但我怀疑这样做是否安全。
我认为最简单的解决方案是使用RefCell>。Box是有大小的,所以当你拥有它时,你可以轻松地构造包含它的RefCell。注意,在你的问题中,你几乎已经写出了这个解决方案,因为Vec::into_boxed_slice(Vec::from(x))不返回[T](因为它是!Sized),而是返回Box<[T]>,然后你可以将其存储在Rc(或RefCell)中。
作为一种简写,您可以使用impl From<&[T]> for Box<[T]>来创建Box<[T]>,然后只需写Box::from(slice)
将所有内容放在一起,这是一个您可以使用的片段。
let slice: &[i32] = &[];
let boxed: Box<[i32]> = Box::from(slice);
let cell: RefCell<Box<[i32]>> = RefCell::new(boxed);
let cell: Rc<RefCell<Box<[i32]>>> = Rc::new(cell);

最后要记住的是,当你有一个`Box<[T]>`时,你可以使用`DerefMut`来获取一个`&mut [T]`,这样你就可以改变切片的元素,但不能扩展或缩短它。要做到这一点,你需要一个`Vec`。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接