copycat/src/memory.rs

76 lines
1.9 KiB
Rust

/*
* 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<const N: usize>(&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<const N: usize>(&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"));
}
}
}