Skip to content

Commit e972f55

Browse files
authored
fix: Optimize environ.rs to avoid redundant string allocations (#304)
* fix: Use HashSet instead of Vec for modifiers 1. Used HashSet<Modifier> instead of Vec for faster checks 2. Removed unnecessary .clone() calls 3. Replaced manual iterations over modifiers with HashSet ordered comparisons. 4. Instead of looping manually to unbind, use .extend() 5. Modified the test to account for the changes above * fix: Use Cow for optimized string copy This commit makes `environ.rs` more optimized by removing redundant `.to_string()` allocations by using Cow (copy-on-write). 1. Used filter_map for single pass instead of manual iteration through env.lines() 2. Replace most .to_string() with Cow to remove unnecessary string allocations 3. In `construct` function, used `env::vars.collect()` to get all values in one pass instead of allocation new string, also now returns env::vars by default instead of an empty HashMap<String, String>
1 parent 6fbaa31 commit e972f55

File tree

1 file changed

+37
-36
lines changed

1 file changed

+37
-36
lines changed

swhkd/src/environ.rs

Lines changed: 37 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,67 +1,68 @@
1-
use std::{collections::HashMap, path::PathBuf};
1+
use std::{borrow::Cow, collections::HashMap, env, path::PathBuf};
22

33
#[derive(Debug, Clone)]
44
pub struct Env {
55
pub pairs: HashMap<String, String>,
66
}
77

88
impl Env {
9+
/// Parses an environment string into key-value pairs.
910
fn parse_env(env: &str) -> HashMap<String, String> {
10-
let mut pairs = HashMap::new();
11-
for line in env.lines() {
12-
let mut parts = line.splitn(2, '=');
13-
if let (Some(key), Some(value)) = (parts.next(), parts.next()) {
14-
pairs.insert(key.to_string(), value.to_string());
15-
}
16-
}
17-
pairs
11+
env.lines()
12+
.filter_map(|line| {
13+
let mut parts = line.splitn(2, '=');
14+
Some((parts.next()?.to_string(), parts.next()?.to_string()))
15+
})
16+
.collect()
1817
}
1918

20-
/// Construct the env from the environment variables
19+
/// Constructs an environment structure from the given string or system environment variables.
2120
pub fn construct(env: Option<&str>) -> Self {
22-
let env = match env {
23-
Some(env) => env.to_string(),
24-
None => "".to_string(),
25-
};
26-
let pairs = Self::parse_env(&env);
21+
let pairs = env.map(Self::parse_env).unwrap_or_else(|| env::vars().collect());
2722
Self { pairs }
2823
}
2924

25+
/// Fetches the HOME directory path.
3026
pub fn fetch_home(&self) -> Option<PathBuf> {
31-
let home = match self.pairs.get("HOME") {
32-
Some(it) => it,
33-
None => return None,
34-
};
35-
Some(PathBuf::from(home))
27+
self.pairs.get("HOME").map(PathBuf::from)
3628
}
3729

30+
/// Fetches the XDG config path.
3831
pub fn fetch_xdg_config_path(&self) -> PathBuf {
39-
let default = match self.fetch_home() {
40-
Some(x) => x.join(".config"),
41-
None => PathBuf::from("/etc"),
42-
}
43-
.to_string_lossy()
44-
.to_string();
45-
let xdg_config_home = self.pairs.get("XDG_CONFIG_HOME").unwrap_or(&default);
32+
let default = self
33+
.fetch_home()
34+
.map(|home| home.join(".config"))
35+
.unwrap_or_else(|| PathBuf::from("/etc"))
36+
.to_string_lossy() // Convert PathBuf -> Cow<'_, str>
37+
.into_owned();
38+
39+
let xdg_config_home =
40+
self.pairs.get("XDG_CONFIG_HOME").map(String::as_str).unwrap_or(&default);
4641

4742
PathBuf::from(xdg_config_home).join("swhkd").join("swhkdrc")
4843
}
4944

45+
/// Fetches the XDG data path.
5046
pub fn fetch_xdg_data_path(&self) -> PathBuf {
51-
let default = match self.fetch_home() {
52-
Some(x) => x.join(".local").join("share"),
53-
None => PathBuf::from("/etc"),
54-
}
55-
.to_string_lossy()
56-
.to_string();
57-
let xdg_config_home = self.pairs.get("XDG_DATA_HOME").unwrap_or(&default);
47+
let default = self
48+
.fetch_home()
49+
.map(|home| home.join(".local/share"))
50+
.unwrap_or_else(|| PathBuf::from("/etc"))
51+
.to_string_lossy()
52+
.into_owned();
53+
54+
let xdg_data_home = self.pairs.get("XDG_DATA_HOME").map(String::as_str).unwrap_or(&default);
5855

59-
PathBuf::from(xdg_config_home)
56+
PathBuf::from(xdg_data_home)
6057
}
6158

59+
/// Fetches the XDG runtime directory path for the given user ID.
6260
pub fn xdg_runtime_dir(&self, uid: u32) -> PathBuf {
6361
let default = format!("/run/user/{}", uid);
64-
let xdg_runtime_dir = self.pairs.get("XDG_RUNTIME_DIR").unwrap_or(&default);
62+
63+
let xdg_runtime_dir =
64+
self.pairs.get("XDG_RUNTIME_DIR").map(String::as_str).unwrap_or(&default);
65+
6566
PathBuf::from(xdg_runtime_dir)
6667
}
6768
}

0 commit comments

Comments
 (0)