1use crate::handle::Handle;
3use crate::id::Id;
4
5pub trait Handled {
7 fn handles(&self) -> &[Handle];
8 fn id(&self) -> &Id;
9}
10
11pub trait AsHandleOrId {
12 fn match_case<T>(
13 &self,
14 case_id: impl FnOnce(&Id) -> T,
15 case_handle: impl FnOnce(&Handle) -> T,
16 ) -> T;
17}
18
19impl AsHandleOrId for Handle {
20 fn match_case<T>(
21 &self,
22 _case_id: impl FnOnce(&Id) -> T,
23 case_handle: impl FnOnce(&Handle) -> T,
24 ) -> T {
25 case_handle(self)
26 }
27}
28
29impl AsHandleOrId for Id {
30 fn match_case<T>(
31 &self,
32 case_id: impl FnOnce(&Id) -> T,
33 _case_handle: impl FnOnce(&Handle) -> T,
34 ) -> T {
35 case_id(self)
36 }
37}
38
39#[derive(Clone)]
40pub struct Map<T: Handled> {
41 value_by_id: std::collections::HashMap<Id, T>,
42 id_by_handle: std::collections::HashMap<Handle, Id>,
43}
44
45impl<T: Handled> Map<T> {
46 pub fn get<Q>(&self, k: &Q) -> Option<&T>
47 where
48 Q: AsHandleOrId,
49 {
50 k.match_case::<Option<&T>>(
51 |id| self.value_by_id.get(id),
52 |handle| self.value_by_id.get(self.id_by_handle.get(handle)?),
53 )
54 }
55
56 #[must_use]
59 pub fn insert_new(&mut self, value: T) -> Option<HandleOrId> {
60 let id: Id = *value.id();
61
62 if self.value_by_id.contains_key(&id) {
64 return Some(id.into());
65 }
66
67 for handle in value.handles() {
68 if self.id_by_handle.contains_key(handle) {
69 return Some(handle.clone().into());
70 }
71 }
72
73 for handle in value.handles() {
74 assert!(self.id_by_handle.insert(handle.clone(), id).is_none());
75 }
76
77 assert!(self.value_by_id.insert(id, value).is_none());
78
79 None
80 }
81
82 pub fn values(&self) -> std::collections::hash_map::Values<'_, Id, T> {
84 self.value_by_id.values()
85 }
86}
87
88impl<T: Handled> Default for Map<T> {
91 fn default() -> Self {
92 Map {
93 value_by_id: Default::default(),
94 id_by_handle: Default::default(),
95 }
96 }
97}
98
99pub enum HandleOrId {
100 Handle(Handle),
101 Id(Id),
102}
103
104impl std::fmt::Display for HandleOrId {
105 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
106 match &self {
107 HandleOrId::Handle(handle) => handle.fmt(f),
108 HandleOrId::Id(id) => id.fmt(f),
109 }
110 }
111}
112
113impl From<Id> for HandleOrId {
114 fn from(id: Id) -> Self {
115 HandleOrId::Id(id)
116 }
117}
118
119impl From<Handle> for HandleOrId {
120 fn from(handle: Handle) -> Self {
121 HandleOrId::Handle(handle)
122 }
123}