rustenumsstaticglobal

rust: static map initialization with enum keys


First up: I am a very newbie with Rust; learning.

This issue arises most probably from thinking in terms of other languages. So most probably the best solution is doing this in a completely different way. Things don't even compile yet, so apologies if the code has fundamental problems.

I am defining my first trait. The trait function takes 2 parameters, which will define the output.

trait SkFormatter {
  fn to_sk(&self, key:Key, is_foreign: bool) -> String;
}

The idea is that the implementation would take a string variable, then prepend a string depending on the key, and append a string if is_foreign (this latter part is not relevant to the question).

E.g.

MT-1c2af34
WD-54bdf36-FX
WD-ad3425b

As those strings are constant, I was thinking I could do this as a global mapping. So I first created

pub enum Key {
  // there are 7 items, but keeping it short here
  Metal,
  Wood,
}

Then I wanted to create the mapping, and things started to get tricky. Tried the HashMap first:

use std::collections::HashMap;
static KEY_TO_PRE:HashMap<Key,&str> = HashMap::from([
  (Key::Metal,"MT-"),
  (Key::Wood, "WD-"),
]);

But this was complaining with

the trait bound Key: std::hash::Hash is not satisfied

Which is surprising to me, as it seems to suggest that the key is not hashable, but I am not defining a type for it, and I would assume that a "unit-like" enum type, as documented, is some kind of integer or something?

I have seen the match idiom, maybe I should try that just inside the implementation (global resp. static stuff is smelly to me), but it's not clear to me if the match thing optimizes for reusing, as it will be called over and over.

Just learning...


Solution

  • But this was complaining with

    the trait bound Key: std::hash::Hash is not satisfied

    Which is surprising to me, as it seems to suggest that the key is not hashable, but I am not defining a type for it, and I would assume that a "unit-like" enum type, as documented, is some kind of integer or something?

    The answer to this is to derive the necessary traits on your key type:

    #[derive(Clone, Copy, PartialEq, Eq, Hash)]
    pub enum Key {
      // there are 7 items, but keeping it short here
      Metal,
      Wood,
    }
    

    I have seen the match idiom, maybe I should try that just inside the implementation (global resp. static stuff is smelly to me), but it's not clear to me if the match thing optimizes for reusing, as it will be called over and over.

    I'm not sure what you mean by "optimizes for reusing". But generally we would use match if all the strings are known at compile time:

    impl Key {
        fn to_prefix(self) -> &'static str {
            match self {
                Self::Metal => "MT-",
                Self::Wood => "WD-",
                // etc
            }
        }
    }
    

    Then use that in your to_sk function.