fn transmute(p: &u8) -> Result<&u64, String> { let u8_p = p as *const u8; let u64_p = u8_p as *const u64; if u64_p as usize % 8 != 0 { return Err(String::from("not aligned")); } unsafe { return Ok(&*u64_p); } } fn transmute_mut(p: &mut u8) -> Result<&mut u64, String> { let u8_p = p as *mut u8; let u64_p = u8_p as *mut u64; if u64_p as usize % 8 != 0 { return Err(String::from("not aligned")); } unsafe { return Ok(&mut *u64_p); } } pub struct Heap { heap: Vec, } pub struct Pointer(usize); impl Heap { pub fn new() -> Self { Heap { heap: vec![0; 128], // 1 kB } } pub fn alloc(&mut self, n: usize) -> Pointer { let p = Pointer(self.heap.len()); self.heap.append(&mut vec![0; n]); p } pub fn peek(&self, p: Pointer) -> Result { let Pointer(x) = p; let u8_p = &self.heap[x]; let u64_p = transmute(u8_p)?; Ok(*u64_p) } pub fn poke(&mut self, u: u64, p: Pointer) -> Result<(), String> { let Pointer(x) = p; let u8_p = &mut self.heap[x]; let u64_p = transmute_mut(u8_p)?; *u64_p = u; Ok(()) } pub fn peek_byte(&self, p: Pointer) -> u8 { let Pointer(x) = p; self.heap[x] } pub fn poke_byte(&mut self, u: u8, p: Pointer) { let Pointer(x) = p; self.heap[x] = u; } } impl Pointer { pub fn from_bytes(p: u64) -> Self { Pointer(usize::try_from(p).unwrap() >> 1) } pub fn bytes(&self) -> u64 { let Pointer(x) = self; u64::try_from(*x).unwrap() << 1 } pub fn offset(&self, off: u8) -> Pointer { let Pointer(x) = self; Pointer(*x + usize::from(off)) } }