1

I have a HashMap with endpoints:

#[derive(Debug, Clone, Copy, Ord, Eq, PartialOrd, PartialEq, Hash)]
enum Endpoint {
    OauthToken,
    Disciplines,
    PublicTournaments,
    MyTournaments,
    Matches,
}

lazy_static! {
    static ref API_EP: HashMap<Endpoint, &'static str> = {
        let mut m: HashMap<Endpoint, &'static str> = HashMap::new();
        m.insert(Endpoint::OauthToken, "/oauth/v2/token");
        m.insert(Endpoint::Disciplines, "/v1/disciplines");
        m.insert(Endpoint::PublicTournaments, "/v1/tournaments");
        m.insert(Endpoint::MyTournaments, "/v1/me/tournaments");
        m.insert(Endpoint::Matches, "/v1/tournaments/{}/matches");
        m
    };
}

As you may see, the map item which is accessible by Endpoint::Matches key returns a string which needs to be formatted, however, I don't see a way of doing this.

I've tried to use format! macro but it needs string literals but not an object so it does not work. I tried to search the solution over the internet and rust std library but I was unable to find it. Is there any way to do this?

For clarification why format! does not work:

error: format argument must be a string literal.
   --> src/lib.rs:249:31
    |
249 |         let address = format!(get_ep_address(Endpoint::Matches)?, id.0);

get_ep_address(Endpoint::Matches)? is not a string literal so it can't work.

I would also like to know how to format both &str and String types.

VP.
  • 15,509
  • 17
  • 91
  • 161
  • 1
    @erip: That's exactly the difference between a literal and a NOT literal. – Matthieu M. Jan 24 '17 at 12:47
  • @MatthieuM. Whoops, overlooked that bit, hehe. – erip Jan 24 '17 at 12:49
  • Very interesting. It appears that you will need a literal format string -- everything seems to revolve around `format_args!()`, which imposes this limitation. It actually makes sense because the compiler ensures the validity of the formatting operation, it cannot be delayed to run-time. – Frédéric Hamidi Jan 24 '17 at 12:52
  • 1
    I [used this a while ago](https://github.com/vitiral/strfmt) while playing around with string formatting. – Simon Whitehead Jan 24 '17 at 13:31

1 Answers1

3

The format! macro expects a literal because it invokes compiler magic (format_args!) to check the format at compile and ensure that its arguments implement the necessary trait. For example {} requires that the argument implements Display, as described in Formatting traits.

You might be able to cobble something together by reaching to Formatter directly, but it means parsing the str yourself.


Note: Rust does not feature reflection, so checking whether a type implements a given trait at runtime is not easy...

Matthieu M.
  • 287,565
  • 48
  • 449
  • 722