Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Looking for a C memcpy equivalent

Tags:

rust

Most efficient (not secure) way to write bytes from src to dst

I found copy_nonoverlapping

pub unsafe fn copy_nonoverlapping(src: *const T, dst: *mut T, count: usize)
Copies count * size_of::() bytes from src to dst. The source and destination must not overlap

The data I am looking to write is located in buf at index 4 and I want to write it in _bytes_buff at (variable) index index * MAX_DATA_LENGTH. MAX_DATA_LENGTH is about 64Kb.

However I have some trouble to make it work. See below snippet of my current attempt to write it properly:

let mut  _bytes_buf:Vec<u8>; // big buffer, we don't know the total size at compilation
let mut buf = [0u8; MAX_DATA_LENGTH]; // small buffer

// [...] we now know the size, I write '3' below to make it simple

let len:usize = MAX_DATA_LENGTH * 3 as usize;
_bytes_buf = Vec::with_capacity(len); // any difference with !vec[0; len] ?
unsafe { _bytes_buf.set_len(len); }

// [...] each time buf has a different content and index is either 0, 1 or 2.

unsafe {
    let dst_ptr = &_bytes_buf[index * MAX_DATA_LENGTH].offset(MAX_DATA_LENGTH as isize); 
    let src_ptr = &buf[4];
    ptr::copy_nonoverlapping(src_ptr, dst_ptr, MAX_DATA_LENGTH);
}

How could I make it work (the last unsafe block)? I found many information but some are deprecated or outdated so I am looking for the way to do it as of 2021.

Also if it is not optimal way to do it (copy_nonoverlapping) I would be very grateful to learn more about how I should do it!

like image 853
Antonin GAVREL Avatar asked Mar 28 '26 02:03

Antonin GAVREL


1 Answers

Rust's safe version of memcpy is <[u8]>::copy_from_slice:

const MAX_DATA_LENGTH: usize = 64000;

let mut bytes_buf = vec![0u8; MAX_DATA_LENGTH * 3];
let buf = [0u8; MAX_DATA_LENGTH];
let index = 0;

bytes_buf[index*MAX_DATA_LENGTH..(index+1)*MAX_DATA_LENGTH-4].copy_from_slice(&buf[4..]);

If you really want to the more direct equivalent, copy_nonoverlapping, this is how to do it:

unsafe {
    let dst_ptr = &mut bytes_buf[index*MAX_DATA_LENGTH] as *mut u8;
    let src_ptr = &buf[4] as *const u8;
    std::ptr::copy_nonoverlapping(src_ptr, dst_ptr, MAX_DATA_LENGTH-4);
}

However, don't use unsafe unless necessary and you understand the safety guarantees you need to ensure to make it safe.

like image 95
kmdreko Avatar answered Mar 31 '26 04:03

kmdreko



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!