Color struct layout

I have this struct:

pub struct Color
{
    bgra: u32,
    b: u8,
    g: u8,
    r: u8,
    a: u8
}

Is it possible that the b.g.r.a fields are inside the address of the bgra field?

  • bgra is at offset 0
  • b is at offset 0
  • g is at offset 1
  • r is at offset 2
  • a is at offset 3

This would save instructions when wanting to extract the red green blue alpha fields.

If not what would be the best way to handle it?

1 Like

No; all struct fields are required to be disjoint. You can do something similar with bytemuck, though you might have some surprises if you compile for an opposite-endian architecture:

use bytemuck;

#[derive(bytemuck::Pod, bytemuck::Zeroable, Copy, Clone)]
#[repr(C, align(4))]
struct Color {
    b: u8,
    g: u8,
    r: u8,
    a: u8,
}

impl Color {
    pub fn as_mut_u32(&mut self)->&mut u32 {
        bytemuck::cast_mut(self)
    }
}

Personally, Iā€™d probably just implement From/Into<u32> and trust the optimizer to do its job properly:

#[derive(Copy, Clone)]
#[repr(align(4))]
struct Color {
    b: u8,
    g: u8,
    r: u8,
    a: u8,
}

impl From<u32> for Color {
    fn from(bgra:u32)->Color {
        let [b,g,r,a] = bgra.to_le_bytes(); // Or to_be_bytes, as appropriate
        Color { b,g,r,a }
    }
}

impl From<Color> for u32 {
    fn from(Color { b,g,r,a }: Color)->u32 {
        u32::from_le_bytes([b,g,r,a]) // Or from_be_bytes, as appropriate
    }
}
4 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.