1use std::collections::hash_map::Entry;
2use std::error::Error;
3use std::fmt;
4
5use rustc_hash::FxHashMap;
6
7#[derive(Debug)]
9pub struct ModelErr(String);
10
11impl ModelErr {
12 pub fn new(message: String) -> ModelErr {
14 ModelErr(format!("Error in problem definition: {message}"))
15 }
16}
17
18impl fmt::Display for ModelErr {
19 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
20 write!(f, "{}", self.0)
21 }
22}
23
24impl Error for ModelErr {}
25
26pub fn get_id(name: &str, name_to_id: &FxHashMap<String, usize>) -> Result<usize, ModelErr> {
27 if let Some(id) = name_to_id.get(name) {
28 Ok(*id)
29 } else {
30 Err(ModelErr::new(format!("no such name `{name}`")))
31 }
32}
33
34pub fn add_name<T>(
35 name: T,
36 names: &mut Vec<String>,
37 name_to_id: &mut FxHashMap<String, usize>,
38) -> Result<usize, ModelErr>
39where
40 String: From<T>,
41{
42 let name = String::from(name);
43
44 match name_to_id.entry(name) {
45 Entry::Vacant(e) => {
46 let id = names.len();
47 names.push(e.key().clone());
48 e.insert(id);
49
50 Ok(id)
51 }
52 Entry::Occupied(e) => Err(ModelErr::new(format!(
53 "name `{key}` is already used",
54 key = e.key()
55 ))),
56 }
57}
58
59#[cfg(test)]
60mod tests {
61 use super::*;
62
63 #[test]
64 fn test_get_id() {
65 let name_to_id = FxHashMap::from(
66 [(String::from("a"), 0), (String::from("b"), 1)]
67 .into_iter()
68 .collect(),
69 );
70
71 let result = get_id("a", &name_to_id);
72 assert!(result.is_ok());
73 assert_eq!(result.unwrap(), 0);
74
75 let result = get_id("b", &name_to_id);
76 assert!(result.is_ok());
77 assert_eq!(result.unwrap(), 1);
78
79 let result = get_id("c", &name_to_id);
80 assert!(result.is_err());
81 }
82
83 #[test]
84 fn test_add_name() {
85 let mut names = Vec::default();
86 let mut name_to_id = FxHashMap::default();
87
88 let result = add_name("a", &mut names, &mut name_to_id);
89 assert!(result.is_ok());
90 assert_eq!(result.unwrap(), 0);
91
92 let result = add_name("b", &mut names, &mut name_to_id);
93 assert!(result.is_ok());
94 assert_eq!(result.unwrap(), 1);
95
96 let result = add_name("a", &mut names, &mut name_to_id);
97 assert!(result.is_err());
98 }
99}