I am learning Rust from the official book, and I have solved the following recommended challenge from the end of chapter 8:
Using a hash map and vectors, create a text interface to allow a user to add employee names to a department in a company. For example, “Add Sally to Engineering” or “Add Amir to Sales.” Then let the user retrieve a list of all people in a department or all people in the company by department, sorted alphabetically.
Are there any bad practices in my code? The code works, and this is the closest form to idiomatic Rust that I could come up with.
use std::io;
use std::collections::HashMap;
enum Command {
Add { name: String, department: String },
List { department: String },
All,
Quit,
}
impl Command {
fn from_string(s: &String) -> Option<Self> {
let el: Vec<&str> = s.trim().split_whitespace().collect();
match el.as_slice() {
["Add", name, "to", department] => Some(Self::Add { name: name.to_string(), department: department.to_string() }),
["List", department] => Some(Self::List { department: department.to_string() }),
["All"] => Some(Self::All),
["Quit"] => Some(Self::Quit),
_ => None,
}
}
fn process(&self, deps: &mut &mut HashMap<String, Vec<String>>) -> bool {
fn print_department(deps: &mut &mut HashMap<String, Vec<String>>, department: String) {
if let Some(v) = deps.get_mut(&department) {
v.sort();
println!("Department {}", department);
for emp in v {
println!("{}", emp);
}
} else {
println!("Invalid department");
}
}
match &self {
Self::Add { name, department } => {
deps.entry(department.to_string()).or_insert(vec![]).push(name.to_string());
false
},
Self::List { department } => {
print_department(deps, department.to_string());
false
},
Self::All => {
for (k, _) in deps.clone() {
print_department(deps, k.to_string());
}
false
},
Self::Quit => {
true
}
}
}
}
fn main() {
let mut deps: HashMap<String, Vec<String>> = HashMap::new();
let mut cmd = String::new();
loop {
cmd.clear();
io::stdin().read_line(&mut cmd).expect("Cannot read command");
match Command::from_string(&cmd) {
Some(cmd) => match cmd.process(&mut &mut deps) {
true => break,
_ => (),
},
None => println!("Invalid command"),
};
}
}