Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Initializing Rc<[u8]> directly without double allocation

Tags:

rust

I am trying to implement deserialization into Rc<[u8]> without double allocating. The solutions I saw always creates an intermediate Vec<u8> and filling it in, and then converting it to an Rc. But this causes double allocation, first when filling in the Vec<u8>, and second converting it into Rc<[u8]>.

Is there a way to directly allocate N bytes (N is read from the deserialization reader) into Rc<[u8]>, and using the buffer as input to the reader? I am OK to unsafe usage as long as there are no memory leaks.

like image 710
Ahmet Yazıcı Avatar asked Aug 31 '26 23:08

Ahmet Yazıcı


1 Answers

This can be accomplished in safe code, by using Rc::from_iter with a TrustedLen iterator:

Iterators of known length

When your Iterator implements TrustedLen and is of an exact size, a single allocation will be made for the Rc<[T]>. For example:

use std::rc::Rc;

pub fn rc_slice<T: Default>(n: usize) -> Rc<[T]> {
    Rc::from_iter((0..n).map(|_| T::default()))
}

fn main() {
    let mut data = rc_slice::<u8>(16);

    // TODO: ovewrite contents of `data` with deserialized data
    *Rc::get_mut(&mut data).unwrap()[0] = ...;
}

Note: This solution relies on a zero/Default initialization of the Rc contents prior to deserialization, which works for u8. If this isn't available for your type, consider using unsafe to allocate an uninitialized Rc-slice.

like image 197
Finn Bear Avatar answered Sep 03 '26 15:09

Finn Bear



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!