4 num::NonZeroU16, |
4 num::NonZeroU16, |
5 ops::{Add, Index, IndexMut}, |
5 ops::{Add, Index, IndexMut}, |
6 }; |
6 }; |
7 |
7 |
8 pub type GearId = NonZeroU16; |
8 pub type GearId = NonZeroU16; |
9 pub trait GearData {} |
|
10 |
9 |
11 #[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Debug)] |
10 #[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Debug)] |
12 #[repr(transparent)] |
11 #[repr(transparent)] |
13 pub struct Millis(u32); |
12 pub struct Millis(u32); |
14 |
13 |
35 fn add(self, rhs: Self) -> Self::Output { |
34 fn add(self, rhs: Self) -> Self::Output { |
36 Self(self.0 + rhs.0) |
35 Self(self.0 + rhs.0) |
37 } |
36 } |
38 } |
37 } |
39 |
38 |
40 pub trait GearDataProcessor<T: GearData> { |
|
41 fn add(&mut self, gear_id: GearId, gear_data: T); |
|
42 fn remove(&mut self, gear_id: GearId); |
|
43 fn get(&mut self, gear_id: GearId) -> Option<T>; |
|
44 } |
|
45 |
|
46 pub trait GearDataAggregator<T: GearData> { |
|
47 fn find_processor(&mut self) -> &mut GearDataProcessor<T>; |
|
48 } |
|
49 |
|
50 pub struct GearAllocator { |
39 pub struct GearAllocator { |
51 max_id: u16, |
40 max_id: u16, |
52 free_ids: BinaryHeap<GearId>, |
41 free_ids: BinaryHeap<GearId>, |
53 } |
42 } |
54 |
43 |
71 |
60 |
72 pub fn free(&mut self, gear_id: GearId) { |
61 pub fn free(&mut self, gear_id: GearId) { |
73 self.free_ids.push(gear_id) |
62 self.free_ids.push(gear_id) |
74 } |
63 } |
75 } |
64 } |
76 |
|
77 #[derive(Clone, Copy, Default)] |
|
78 pub struct LookupEntry<T> { |
|
79 index: Option<NonZeroU16>, |
|
80 value: T, |
|
81 } |
|
82 |
|
83 impl<T> LookupEntry<T> { |
|
84 #[inline] |
|
85 pub fn index(&self) -> u16 { |
|
86 self.index.map(|i| i.get()).unwrap_or(0) - 1 |
|
87 } |
|
88 |
|
89 #[inline] |
|
90 pub fn set_index(&mut self, index: u16) { |
|
91 self.index = unsafe { Some(NonZeroU16::new_unchecked(index.saturating_add(1))) }; |
|
92 } |
|
93 |
|
94 #[inline] |
|
95 pub fn value(&self) -> &T { |
|
96 &self.value |
|
97 } |
|
98 |
|
99 #[inline] |
|
100 pub fn value_mut(&mut self) -> &mut T { |
|
101 &mut self.value |
|
102 } |
|
103 |
|
104 #[inline] |
|
105 pub fn set_value(&mut self, value: T) { |
|
106 self.value = value; |
|
107 } |
|
108 } |
|
109 |
|
110 pub struct GearDataLookup<T> { |
|
111 lookup: Box<[LookupEntry<T>]>, |
|
112 } |
|
113 |
|
114 impl<T: Default + Copy> GearDataLookup<T> { |
|
115 pub fn new() -> Self { |
|
116 Self { |
|
117 lookup: vec![LookupEntry::default(); u16::max_value() as usize].into_boxed_slice(), |
|
118 } |
|
119 } |
|
120 } |
|
121 |
|
122 impl<T> GearDataLookup<T> { |
|
123 pub fn add(&mut self, gear_id: GearId, index: u16, value: T) { |
|
124 // All possible Gear IDs are valid indices |
|
125 let entry = unsafe { self.lookup.get_unchecked_mut(gear_id.get() as usize - 1) }; |
|
126 entry.set_index(index); |
|
127 entry.set_value(value); |
|
128 } |
|
129 |
|
130 pub fn get(&self, gear_id: GearId) -> Option<&LookupEntry<T>> { |
|
131 // All possible Gear IDs are valid indices |
|
132 let entry = unsafe { self.lookup.get_unchecked(gear_id.get() as usize - 1) }; |
|
133 if let Some(index) = entry.index { |
|
134 Some(entry) |
|
135 } else { |
|
136 None |
|
137 } |
|
138 } |
|
139 |
|
140 pub fn get_mut(&mut self, gear_id: GearId) -> Option<&mut LookupEntry<T>> { |
|
141 // All possible Gear IDs are valid indices |
|
142 let entry = unsafe { self.lookup.get_unchecked_mut(gear_id.get() as usize - 1) }; |
|
143 if let Some(index) = entry.index { |
|
144 Some(entry) |
|
145 } else { |
|
146 None |
|
147 } |
|
148 } |
|
149 } |
|
150 |
|
151 impl<T> Index<GearId> for GearDataLookup<T> { |
|
152 type Output = LookupEntry<T>; |
|
153 |
|
154 fn index(&self, index: GearId) -> &Self::Output { |
|
155 self.get(index).unwrap() |
|
156 } |
|
157 } |
|
158 |
|
159 impl<T> IndexMut<GearId> for GearDataLookup<T> { |
|
160 fn index_mut(&mut self, index: GearId) -> &mut Self::Output { |
|
161 self.get_mut(index).unwrap() |
|
162 } |
|
163 } |
|