Strict array literal

#1

Suppose you want to define a lookup table. Naively it could be achieved this way:

#[allow(dead_code)]

enum E{A,B,C,D}

static LOOKUP: [i32;4] = [1,2,3,4];

fn main() {
    println!("{}",LOOKUP[E::A as usize]);
}

But actually we want to express a strict relationship between the enumeration and the lookup table:

enum E{A,B,C,D}

static LOOKUP: [i32;4] = [
    E::A as usize: 1,
    E::B as usize: 2,
    E::C as usize: 3,
    E::D as usize: 4
];

fn main() {
    println!("{}",LOOKUP[E::A as usize]);
}

Additionally, a purified variant could be provided:

enum E{A,B,C,D}

static LOOKUP: [i32;E] = [A: 1, B: 2, C: 3, D: 4];

fn main() {
    println!("{}",LOOKUP[E::A]);
}
0 Likes

#2

Take a look at Ada language, that allows arrays to have specified ranged integrals. A possible Rust syntax:

enum E {A, B, C, D}

fn main() {
    let table: [i32; E] = [1, 2, 3, 4];
    assert_eq!(table[E::A], 1);
}

Some Rust programmer may want to solve that like this, but this misses the point:

#[repr(i32)]
enum E {A = 1, B = 2, C = 3, D = 4}

fn main() {
    println!("{}", E::A as i32);
}
0 Likes

#3

This could be done with a custom newtype (to implement enum-using indexing) backed by a struct of the right size and a custom Derive. Alowing to write code along these lines:

/// Some possible name for the crate.
use ::enum_index::EnumIndex;

#[derive(EnumIndex)]
  // this will declare the struct FooIndex<T : Sized> { A: T, B: T, C: T }
  // and impl<T : Sized> ::std::ops::Index{,Mut}<Foo> for FooIndex<T>
enum Foo {
  A,
  B,
  C,
}

static LOOKUP: FooIndex<i32> = {
    A: 42,
    B: 69,
    C: 0,
};

fn main ()
{
    assert_eq!(LOOKUP.A, 1); // static indexing
    assert_eq!(LOOKUP[Foo::A], 1); // dynamic but unfallible indexing
}

Definitely doable.

0 Likes

#4

Sounds like you’re looking for this crate:

https://crates.io/crates/enum-map

2 Likes