rust/hwphysics/src/common.rs
changeset 15286 8095853811a6
parent 15280 66c987015f2d
child 15287 478d5372eb4a
--- a/rust/hwphysics/src/common.rs	Mon Jul 29 21:58:39 2019 +0200
+++ b/rust/hwphysics/src/common.rs	Tue Jul 30 19:53:23 2019 +0300
@@ -1,10 +1,15 @@
 use fpnum::{fp, FPNum};
-use std::{collections::BinaryHeap, num::NonZeroU16, ops::Add};
+use std::{
+    collections::BinaryHeap,
+    num::NonZeroU16,
+    ops::{Add, Index, IndexMut},
+};
 
 pub type GearId = NonZeroU16;
 pub trait GearData {}
 
 #[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Debug)]
+#[repr(transparent)]
 pub struct Millis(u32);
 
 impl Millis {
@@ -67,3 +72,53 @@
         self.free_ids.push(gear_id)
     }
 }
+
+#[derive(Clone, Copy, Default)]
+pub struct LookupEntry<T> {
+    pub index: u16,
+    pub value: T,
+}
+
+impl<T> LookupEntry<T> {
+    pub fn new(index: u16, value: T) -> Self {
+        Self { index, value }
+    }
+}
+
+pub struct GearDataLookup<T> {
+    lookup: [LookupEntry<T>; u16::max_value() as usize],
+}
+
+impl<T: Default + Copy> GearDataLookup<T> {
+    pub fn new() -> Self {
+        Self {
+            lookup: [LookupEntry::<T>::default(); u16::max_value() as usize],
+        }
+    }
+}
+
+impl<T> GearDataLookup<T> {
+    pub fn get(&self, gear_id: GearId) -> &LookupEntry<T> {
+        // All possible Gear IDs are valid indices
+        unsafe { self.lookup.get_unchecked(gear_id.get() as usize - 1) }
+    }
+
+    pub fn get_mut(&mut self, gear_id: GearId) -> &mut LookupEntry<T> {
+        // All possible Gear IDs are valid indices
+        unsafe { self.lookup.get_unchecked_mut(gear_id.get() as usize - 1) }
+    }
+}
+
+impl<T> Index<GearId> for GearDataLookup<T> {
+    type Output = LookupEntry<T>;
+
+    fn index(&self, index: GearId) -> &Self::Output {
+        self.get(index)
+    }
+}
+
+impl<T> IndexMut<GearId> for GearDataLookup<T> {
+    fn index_mut(&mut self, index: GearId) -> &mut Self::Output {
+        self.get_mut(index)
+    }
+}