2

I want to have an enum where each value in the enum stores a constant array of bytes that represent the RGBA values for a color. In Java I would do this:

public enum Color {
    BLACK([0x0C, 0x00, 0x05, 0xFF]),
    BLUE([0x00, 0x2D, 0xFF, 0xFF]),
    RED([0xFF, 0x3E, 0x00, 0xFF]);

    private final byte[] rgba;

    Color(byte[] rgba) {
      this.rgba = rgba;
    }

    public int[] value() {
      return rgba;
    }
}

Then I could pass around Color types and just use color.value() to get the bytes out. This is what I have in Rust:

struct Color;

impl Color {
    pub const BLACK: [u8; 4] = [0x0C, 0x00, 0x05, 0xFF];
    pub const BLUE: [u8; 4] = [0x00, 0x2D, 0xFF, 0xFF];
    pub const RED: [u8; 4] = [0xFF, 0x3E, 0x00, 0xFF];
}

But this means that anywhere I want to pass a Color the type is [u8; 4]. I could call the struct Colors and then do pub type Color = [u8; 4]. Then you could have the type as Color but then it would be Colors::BLACK which seems weird.

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
CaseyB
  • 24,780
  • 14
  • 77
  • 112
  • 1
    Does this answer your question? [How can I create enums with constant values in Rust?](https://stackoverflow.com/questions/36928569/how-can-i-create-enums-with-constant-values-in-rust) – Aplet123 Jan 05 '21 at 23:54
  • ^ if `Color` can only be black, blue, or red then that's the way to do, but if it can have any r, g, b, a value, then it should probably be `struct Color([u8; 4]);` with your constants defined like `pub const BLACK: Color = Color([...]);` – kmdreko Jan 06 '21 at 00:04

2 Answers2

6

If you want to have a strong type for the byte array in the Color struct, you can use the following notation, called a tuple struct:

struct Color([u8; 4]);

impl Color {
    pub const BLACK: Color = Color([0x0C, 0x00, 0x05, 0xFF]);
    pub const BLUE: Color = Color([0x00, 0x2D, 0xFF, 0xFF]);
    pub const RED: Color = Color([0xFF, 0x3E, 0x00, 0xFF]);
}

fn main() {
    // classic way of accessing data
    println!("{:?}", Color::BLACK.0);
    
    // using destructuring
    let Color(bytes) = Color::BLUE;
    println!("{:?}", bytes);
}

Playground link

SirDarius
  • 41,440
  • 8
  • 86
  • 100
0

I have created a crate enumeration just for this.

Example using my crate:

use enumeration::prelude::*;

enumerate!(pub Color(u8; [u8; 4])
    Black = [0x0C, 0x00, 0x05, 0xFF]
    Blue = [0x00, 0x2D, 0xFF, 0xFF]
    Red = [0xFF, 0x3E, 0x00, 0xFF]
);

pub fn main() {
    assert_eq!(*Color::Black.value(), [0x0C, 0x00, 0x05, 0xFF]);
    assert_eq!(*Color::Blue.value(), [0x00, 0x2D, 0xFF, 0xFF]);
    assert_eq!(*Color::Red.value(), [0xFF, 0x3E, 0x00, 0xFF]);
}
feois
  • 21
  • 3
  • 1
    I think using a library is overkill for this. I think [this answer](https://stackoverflow.com/a/36928678/2037998) fixes the problem in a much simpler way. – Ralph Bisschops Jun 05 '22 at 12:28
  • @RalphBisschops actually my macro does just that, it just produces enum with method that uses `match` and I tried my best to make it small (no dependency and only a macro) – feois Jun 06 '22 at 12:34