4

I am looking to build an array that will be copied into RAM and sent to an LCD driver. I would like to be able to pass in a color value (color: u16) and use it to populate the array. Note that I am using #![no_std] as this is intended for an embedded application.

The obvious simple approach would be as follows:

let mut block: [u8;256] = [0; 256];
for i in (0..block.len()).step_by(2) {
    block[i] = ((color && 0xFF00) >> 8) as u8;
    block[i+1] = (color && 0xFF) as u8;
}

As more of my personal experience comes from C, I wondered if there were any better solutions using type casting and conversion. For example, using Rust to initialize a u16 array and cast as a u8 array:

let block_u16: [u16; 128] = [color; 128]
let block_u8 = block_u16 as [u8; 256];

For reference, the target function prototype is:

spi::setup_block(block: &[u8]);
trent
  • 25,033
  • 7
  • 51
  • 90

3 Answers3

6

You could go the unsafe route via transmute, but I would not recommend it. I would not vouch for a C-style version to do the same on a little and big-endian machine.

Personally I would take the chunk iterator over the slice.

let color_bytes = color.to_le_bytes();
for word in block.chunks_exact_mut(2) {
    word[0] = color_bytes[0];
    word[1] = color_bytes[1];
}
Markus Klein
  • 1,202
  • 12
  • 10
1

You could use something like your second approach (casting the u16 array to a u8 pointer).

let color: u16 = 0x0102;
let mut block: [ u16; 128 ] = [ color; 128 ];
let mut block = unsafe { 
    core::slice::from_raw_parts_mut( block.as_mut_ptr( ) as *mut u8, block.len( ) * 2 ) 
};

Beware of endianness with this solution, it might not do what you want on your target architecture.

WBuck
  • 5,162
  • 2
  • 25
  • 36
  • I will try using this and post results. Thank you – Taylor Spencer Mar 18 '21 at 20:38
  • 1
    For anyone considering using this: note that it's important `block` is declared as **`[u16; 128]`** and not `[u8; 256]`, since if it is not properly aligned, `slice::from_raw_parts_mut` will invoke UB. – trent Mar 20 '21 at 14:57
0
for chunk in block.chunks_exact_mut(2) {
    chunk.copy_from_slice(&color.to_be_bytes());
}
Tomek Czajka
  • 481
  • 3
  • 8
  • Please don't post only code as answer, but also provide an explanation what your code does and how it solves the problem of the question. Answers with an explanation are usually more helpful and of better quality, and are more likely to attract upvotes. – Mark Rotteveel Mar 20 '21 at 09:55