mindustry logic execution, map- and schematic- parsing and rendering
Diffstat (limited to 'lemu/src/memory.rs')
| -rw-r--r-- | lemu/src/memory.rs | 32 |
1 files changed, 18 insertions, 14 deletions
diff --git a/lemu/src/memory.rs b/lemu/src/memory.rs index 133fe8e..ff99dc8 100644 --- a/lemu/src/memory.rs +++ b/lemu/src/memory.rs @@ -39,11 +39,14 @@ impl LVar<'_> { #[derive(Clone, Copy)] pub struct LAddress { - pub address: u16, + pub address: u32, } impl LAddress { - pub(crate) const fn addr(address: u16) -> Self { + /// # Safety + /// + /// ensure that address is valid + pub(crate) const unsafe fn addr(address: u32) -> Self { LAddress { address } } } @@ -98,27 +101,27 @@ impl<'s> From<Cow<'s, str>> for LVar<'s> { } } -/// whats a megabyte among friends #[derive(Debug)] -pub struct LRegistry<'str>(pub Box<[LVar<'str>; 65536]>); +pub struct LRegistry<'str>(pub Box<[LVar<'str>]>); impl<'s> std::ops::Index<LAddress> for LRegistry<'s> { type Output = LVar<'s>; fn index(&self, index: LAddress) -> &Self::Output { - &self.0[index.address as usize] + debug_assert!((index.address as usize) < self.0.len()); + // SAFETY: LAddress promises to be in our bounds. + // lreg has no constructors, so unless you keep one around, grab a laddr, and use it on the old lreg, + // this is safeish. + // lreg is private to the outside world, so its ok + unsafe { self.0.get_unchecked(index.address as usize) } } } impl<'s> std::ops::IndexMut<LAddress> for LRegistry<'s> { fn index_mut(&mut self, index: LAddress) -> &mut Self::Output { - &mut self.0[index.address as usize] - } -} - -impl<'s> Default for LRegistry<'s> { - fn default() -> Self { - Self(vec![LVar::null(); 65536].try_into().unwrap()) + debug_assert!((index.address as usize) < self.0.len()); + // SAFETY: see above + unsafe { self.0.get_unchecked_mut(index.address as usize) } } } @@ -156,9 +159,10 @@ impl Printable for LRegistry<'_> { let mut iter = self .0 .iter() - .zip(0..u16::MAX) + .zip(0..self.0.len() as u32) .filter(|&(v, _)| v != &LVar::null()) - .map(|(v, i)| (&info[LAddress::addr(i)], v)) + // SAFETY: the address comes from me + .map(|(v, i)| (&info[unsafe { LAddress::addr(i) }], v)) .filter_map(|(d, v)| match d { VarData::Variable(d) => Some((*d, v)), VarData::Constant(_) => None, |