How do I save a environment variable into HashMap?

Hi,

I'm having a HashMap like below:

pub struct Record {
    env: Option<HashMap<&'static str, &'static str>>,
}

How can I save a environment variable into that Record.env dict? like this?

let env = self.env.get_or_insert(HashMap::new());
env.insert("SHELL", "powershell.exe");
let term: String = env::var("TERMINAL_EMULATOR").unwrap_or("UnKnown".to_string());
env.insert("TERM", &term);

I've been searching around online for several hours. And found some answers that suggest that I should use HashMap<String, String> instead of HashMap<&str, &str> and there was even a PR that updates the official Rust exmaples to use HashMap<String> instead of &str.

I'm just new to Rust and super curious is that possible to save the env var into a HashMap<&str, &str> and if it can, why is it so hard?

If not, why? as I can easily save string literals, which is &static str if I'm not wrong, into the HashMap.

Assuming that I'm having the correct under standing of String and &str: basically &str is a char * and String is just a "boxed string" object

Thanks,

You can't put it in a HashMap<_, &'static str> because it isn't 'static - env::var returns a String, which you have to keep ownership of alive. That's why you can use a HashMap<&'static str, String>:

ev.insert("SHELL", "powershell.exe".to_string());
let term = env::var("TERMINAL_EMULATOR").unwrap_or("Unknown".to_string());
ev.insert("TERM", term);

Rust makes this hard because not all OSes give static references to environment variables - Windows, for instance, requires you give it a buffer to fill the environment variable value with, and that buffer's lifetime has to be maintained by someone.

1 Like

thanks @asymmetrikon

to follow up:

is there anyway to make the String to be 'static ?

If I dare to ask more, why would a language implementation be limited/strict by the way the OS API?

I mean, no matter how Windows provides the value to Rust, the language should be able to convert it into it's own representation right? Because in anyway, a "environment variable" is just a type of "string" in general?

In this particular case, on Windows, the buffer that Rust is giving to, whose lifetime can be maintained by the owning HashMap, in theory, right? or I'm missing anything here?

could you point me some link to learn more about this?

I miswrote a bit; Strings are 'static, since if you have ownership of one you can make it last forever. However, references to a variable can last only as long as the variable does, so if you take a reference to a String that is dropped at the end of the block/function (like your term is,) the reference can't last any longer than that. There is a way to get a &'static str from a String - you can turn it into a Box<str> and leak that using Box::leak - but it's not really necessary here, and I wouldn't do it without understanding that it does leak memory.

Rust is a low-level language, which means it cares a great deal about how memory is allocated and handled. It doesn't do any of these conversions on its own - it relies on the user to specify exactly how they want variables in memory to hang around, which you do by passing around ownership of values.

That's what having it own Strings is doing. A HashMap<&str, &str> can't maintain ownership of anything since it only contains references, not actual values.

This chapter of the book is probably a good starting place to understanding Rust's ownership system.

1 Like

Thank you so much for the detailed explanation!

will learn more about this.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.