/* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ use std::alloc::{alloc, dealloc, Layout}; mod consts { #![allow(non_upper_case_globals)] pub const KiB: u64 = 1024; pub const MiB: u64 = 1024 * KiB; } pub use consts::*; pub struct Memory { memory: *mut u8, memory_size: u64, } impl Memory { pub fn new(size: u64) -> Self { Self { memory: unsafe { alloc(Layout::from_size_align(size.try_into().unwrap(), 1 * MiB as usize).expect("layout error")) }, memory_size: size, } } pub fn read(&self, address: u64) -> [u8; N] { if address >= self.memory_size { return [0; N]; } unsafe { self.memory.offset(address.try_into().unwrap()).cast::<[u8; N]>().read_unaligned() } } pub fn write(&mut self, address: u64, value: [u8; N]) { if address >= self.memory_size { return; } unsafe { self.memory.offset(address.try_into().unwrap()).cast::<[u8; N]>().write_unaligned(value); } } pub fn read_u8(&self, address: u64) -> u8 { self.read::<1>(address)[0] } pub fn write_u8(&mut self, address: u64, value: u8) { self.write::<1>(address, [value]); } pub fn read_u16(&self, address: u64) -> u16 { u16::from_le_bytes(self.read::<2>(address)) } pub fn write_u16(&mut self, address: u64, value: u16) { self.write::<2>(address, value.to_le_bytes()); } } impl Drop for Memory { fn drop(&mut self) { unsafe { dealloc(self.memory, Layout::from_size_align(self.memory_size.try_into().unwrap(), 1 * MiB as usize).expect("layout error")); } } }