1use std::collections::HashMap;
2use std::hash::Hash;
3use std::fmt::Display;
4
5pub trait Registrable<ID: Eq + Hash> {
7 fn get_name(&self) -> &'static str;
8 fn get_id(&self) -> ID;
9}
10
11
12pub struct Registry<ID: Eq + Hash, T: Registrable<ID>> {
15 data: Vec<T>,
16 by_names: HashMap<&'static str, usize>,
17 by_ids: HashMap<ID, usize>
18}
19
20
21impl<ID, T> Registry<ID, T>
22where
23 ID: Eq + Hash,
24 T: Registrable<ID>
25{
26
27 pub fn new() -> Self {
28 Registry {
29 data: Vec::new(),
30 by_names: HashMap::new(),
31 by_ids: HashMap::new()
32 }
33 }
34
35 pub fn register(&mut self, item: T) -> bool {
36
37 if self.by_names.contains_key(&item.get_name()) ||
38 self.by_ids.contains_key(&item.get_id()) {
39
40 false
41
42 } else {
43
44 let idx = self.data.len();
45 self.by_names.insert(item.get_name(), idx);
46 self.by_ids.insert(item.get_id(), idx);
47 self.data.push(item);
48
49 true
50
51 }
52
53 }
54
55 pub fn get_from_name(&self, name: &str) -> Option<&T> {
56 Some(&self.data[*self.by_names.get(&name)?])
57 }
58
59 pub fn get_from_id(&self, id: ID) -> Option<&T> {
60 Some(&self.data[*self.by_ids.get(&id)?])
61 }
62
63 pub fn expect_from_name(&self, name: &str) -> &T {
64 self.get_from_name(name).expect(format!("Missing name '{}' in the registry.", name).as_str())
65 }
66
67 pub fn expect_from_id(&self, id: ID) -> &T
68 where
69 ID: Display + Copy
70 {
71 self.get_from_id(id).expect(format!("Missing id '{}' in the registry.", id).as_str())
72 }
73
74 pub fn check_if_exists<'a>(&self, item: &'a T) -> &'a T {
75 if !self.by_ids.contains_key(&item.get_id()) {
76 panic!("The item '{}' is not registered.", item.get_name());
77 } else {
78 item
79 }
80 }
81
82}