Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I intialize an Rc<RefCell<[u8]>> from a &[u8]?

Tags:

rust

Note that the slice is unsized. I'm fine with doing a memory allocation/copy, or transferring ownership.

I know that to make simply an Rc<[u8]>, I can use Rc::from(Vec::into_boxed_slice(Vec::from(x))), but this approach doesn't work with the added RefCell. I note that RefCell<T> allows T: ?Sized, but it seems like in practice it's hard to actually construct a RefCell containing an unsized type?

like image 626
ajp Avatar asked Oct 12 '25 23:10

ajp


1 Answers

RefCell doesn't use indirection like Box or Rc, but instead it stores it's data on the stack. Here is a simplified definition of RefCell and UnsafeCell (both from the 1.70.0 version).

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

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

RefCell can hold Ts that are not Sized, but then it itself becomes !Sized. There might be some way to create (some indirection) RefCell<[T]> using unsafe code, but I doubt It can be done safely.

The easiest solution, I believe, would be to use RefCell<Box<[T]>> instead. Box is sized, so when you have it, you can trivially construct RefCell containing it. Note, that you have almost written this solution in your question, because Vec::into_boxed_slice(Vec::from(x)) doesn't return [T] (as it is !Sized), but rather Box<[T]> which you then can store inside Rc (or RefCell).

As a shorthand you can create Box<[T]> using impl From<&[T]> for Box<[T]>, and just write Box::from(slice).

To put it all together here's a snippet that you can use.

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);

As a final note remember that when you have Box<[T]> you can obtain a &mut [T] from it using DerefMut, so you can change elements of the slice, but you cannot extend or shorten it. To do that you would need a Vec.

like image 195
Aleksander Krauze Avatar answered Oct 16 '25 05:10

Aleksander Krauze



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!