McKrassy
McKrassy

Reputation: 991

How to declare/manage constants with non-trivial initialisers

I would like to initialise some constants at the very top of my main.rs file, like so:

const PRIVATE_KEY: Vec<u8> = std::fs::read("./jwtRS256.key").unwrap();
const PUBLIC_KEY: Vec<u8> = std::fs::read("./jwtRS256.pub.key").unwrap();

fn main () {
  // do some stuff
}

However, I am getting a compiler error as follows:

error[E0015]: calls in constants are limited to constant functions, tuple structs and tuple variants
  --> src/main.rs:16:30
   |
16 | const PRIVATE_KEY: Vec<u8> = std::fs::read("./jwtRS256.key").unwrap();
   |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

I understand; makes sense. The compiler wants to be able to evaluate the values of these constants at compile time and it can't. What is the alternative, though? I need those constants available all through my code, including in other modules. So, I cannot just move them as regular variables into the main function. What do I do instead? (I am on Rust 1.47.)

Upvotes: 1

Views: 1622

Answers (2)

Masklinn
Masklinn

Reputation: 42562

THere are two possibilities and it's a bit unclear which one you want:

Embed the content of the files in the binary

include_bytes and include_str will read the files during compilation and embed their contents (according to the machine having compiled the binary) in the final program.

Runtime global

If you want to read the files when the program starts and make those contents available globally, you want lazy_static or once_cell instead, they allow running code to initialise a global at runtime.

const v static

static is probably what you want either way, it's much closer to globals in other languages.

const is more macro-ish, all references to the const's name will be replaced by the value, directly.

This is often what you want for e.g. simple numbers (that way they get compiled as immediates rather than loads from memory), but for more complex types or large amounts of data static is generally the better pick.

Upvotes: 4

Aplet123
Aplet123

Reputation: 35560

If these files are present and compile-time and your only goal is to include them in the compilation, then you can simply use include_bytes!("./jwtRS256.key"). However, if you want to read these files at runtime, then consider using lazy_static:

lazy_static! {
    pub static ref PRIVATE_KEY: Vec<u8> = std::fs::read("./jwtRS256.key").unwrap();
}

This crate essentially allows you to lazily initialize static variables and use them anywhere.

Upvotes: 2

Related Questions