pub struct Heap {
memory: Vec<u8>,
allocated: Vec<(usize, usize)>,
allocated_size: usize,
}
type Type = usize;
impl Heap {
pub fn allocate(&mut self, size: usize) -> Result<Type, ()> {
if let Some(start) = self.find_available_space(size) {
let end = start + size - 1;
self.allocated.push((start, end));
for i in start..end {
self.memory[i] = 0;
}
Ok(start)
} else {
segfault(self.memory.len(), "Allocating OOB".to_string(), "allocate");
Err(())
}
}
fn find_available_space(&self, size: usize) -> Option<usize> {
let mut start = 0;
for &(allocated_start, allocated_end) in &self.allocated {
if allocated_start - start >= size {
return Some(start);
}
start = allocated_end + 1;
}
if self.memory.len() - start >= size {
Some(start)
} else {
None
}
}
pub fn free(&mut self, pos: usize) -> Result<(), ()> {
if let Some(start) = self
.allocated
.iter()
.position(|&(start, end)| pos >= start && pos <= end)
{
let range = self.allocated.remove(start);
for i in range.0..=range.1 {
self.memory[i] = 0;
}
Ok(())
} else {
segfault(pos, "out of bounds".to_string(), "free");
Err(())
}
}
pub fn new(size: usize) -> Heap {
Heap {
memory: vec![0; size],
allocated: vec![],
allocated_size: 0,
}
}
pub fn read(&self, pos: usize, size: usize) -> Result<Vec<u8>, ()> {
let mut data = Vec::new();
for i in &self.memory[pos..pos + size] {
data.push(*i);
}
return Ok(data);
}
pub fn realloc(&mut self, pos: usize, size: usize) -> Result<usize, ()> {
let (start, end) = self.allocated[pos];
if self.memory[end..end + size].iter().all(|&x| x == 0) {
self.allocated[pos] = (start, end + size);
for i in start..end + size {
self.memory[i] = 0;
}
return Ok(start);
} else {
let new_pos = self.allocate(size).unwrap();
for i in start..end {
self.memory[new_pos + i] = self.memory[i];
}
self.free(pos).unwrap();
return Ok(new_pos);
}
}
pub fn sizeof(&self, pos: usize) -> Result<usize, ()> {
for (start, end) in self.allocated.iter() {
if pos >= *start && pos <= *end {
return Ok((end - start + 1) * 8);
}
}
segfault(pos, "out of bounds".to_string(), "sizeof");
return Err(());
}
pub fn write(&mut self, pos: usize, data: u8) -> Result<(), ()> {
for (start, end) in self.allocated.iter() {
if pos >= *start && pos <= *end {
self.memory[pos] = data;
return Ok(());
}
}
segfault(pos, "out of bounds".to_string(), "write");
return Err(());
}
}
fn segfault(position: usize, reason: String, func: &str) {
let red = "\x1b[31m";
let reset = "\x1b[0m";
println!(
"{}Segmentation fault{} at {}, position: {}{}{}",
red, reset, func, red, position, reset
);
println!("Reason: {}", reason);
std::process::exit(0)
}
pub struct Stack {
memory: Vec<u8>,
ptr: usize,
}
impl Stack {
pub fn new() -> Stack {
Stack {
memory: vec![0; 8192],
ptr: 0,
}
}
}
impl Stack {
pub fn push(&mut self, data: u8) {
self.memory[self.ptr] = data;
self.ptr += 1;
}
pub fn pop(&mut self) -> u8 {
self.ptr -= 1;
self.memory[self.ptr]
}
pub fn peek(&self) -> u8 {
self.memory[self.ptr - 1]
}
pub fn get(&self, offset: usize) -> u8 {
self.memory[self.ptr - offset]
}
pub fn swap(&mut self) {
let temp = self.memory[self.ptr - 1];
self.memory[self.ptr - 1] = self.memory[self.ptr - 2];
self.memory[self.ptr - 2] = temp;
}
pub fn dup(&mut self) {
self.memory[self.ptr] = self.memory[self.ptr - 1];
self.ptr += 1;
}
pub fn drop(&mut self) {
self.memory[self.ptr] = 0;
self.ptr -= 1;
}
}
impl Default for Stack {
fn default() -> Self {
Self::new()
}
}
impl Default for Heap {
fn default() -> Self {
Self::new(8192)
}
}