Reid/src/file_io.rs

192 lines
6.2 KiB
Rust
Raw Permalink Normal View History

2020-06-21 00:21:24 +02:00
use std::fs::File;
use std::io::prelude::*;
use std::io::BufReader;
use std::path::Path;
use super::errors::GenericError;
use super::vm::VariableType;
2020-07-02 22:13:10 +02:00
use super::vm::{Command, CompiledReid};
2020-06-21 00:21:24 +02:00
2020-07-02 22:13:10 +02:00
#[cfg(feature = "compiler")]
pub fn open_source(path: &Path) -> Result<String, GenericError> {
2020-06-21 00:21:24 +02:00
let file = File::open(path)?;
let mut reader = BufReader::new(file);
let mut text = String::new();
reader.read_to_string(&mut text)?;
Ok(text)
}
2020-07-02 22:13:10 +02:00
#[cfg(feature = "compiler")]
pub fn into_bytecode(compiled: &CompiledReid) -> Vec<u8> {
let mut list = Vec::new();
2020-07-05 21:56:11 +02:00
let cloned = compiled.list.clone().into_iter();
for item in cloned {
list.append(&mut item.into_u8());
}
list
}
2020-07-02 22:13:10 +02:00
#[cfg(feature = "compiler")]
pub fn write_bytecode(bytecode: Vec<u8>, path: &Path) -> Result<(), GenericError> {
let mut file = File::create(path)?;
file.write_all(&bytecode)?;
Ok(())
}
pub fn open_bytecode(path: &Path) -> Result<CompiledReid, GenericError> {
let file = File::open(path)?;
let mut reader = BufReader::new(file);
let mut commands = Vec::new();
let mut iter = reader.fill_buf()?.iter().peekable();
while iter.peek().is_some() {
if let Some(command) = Command::from_u8(&mut iter) {
commands.push(command);
} else {
return Err(GenericError::CorruptedBytecode);
}
}
Ok(CompiledReid { list: commands })
}
impl VariableType {
2020-07-02 22:13:10 +02:00
#[cfg(feature = "compiler")]
2020-07-05 21:56:11 +02:00
fn into_u8(self) -> u8 {
match self {
VariableType::TypeString => 0,
VariableType::TypeI32 => 1,
}
}
fn from_u8(num: u8) -> Option<VariableType> {
match num {
0 => Some(VariableType::TypeString),
1 => Some(VariableType::TypeI32),
_ => None,
}
}
}
impl Command {
2020-07-02 22:13:10 +02:00
#[cfg(feature = "compiler")]
fn id(&self) -> u8 {
match *self {
Command::InitializeVariable(..) => 0,
Command::BeginScope => 1,
Command::EndScope => 2,
Command::Pop(..) => 3,
Command::Push(..) => 4,
Command::AssignVariable(..) => 5,
Command::VarToReg(..) => 6,
Command::StringLit(..) => 7,
Command::I32Lit(..) => 8,
Command::FunctionCall(..) => 9,
2020-07-05 21:20:49 +02:00
Command::Add => 10,
Command::Subtract => 11,
Command::Mult => 12,
2020-07-06 11:42:38 +02:00
Command::Pow => 13,
Command::Div => 14,
2020-07-07 14:06:10 +02:00
Command::Mod => 15,
}
}
fn from_u8<'a, T: Iterator<Item = &'a u8>>(iter: &mut T) -> Option<Command> {
let id = iter.next()?;
match id {
0 => {
let heapid = u16::from_be_bytes([*iter.next()?, *iter.next()?]);
Some(Command::InitializeVariable(
heapid,
VariableType::from_u8(*iter.next()?)?,
))
}
1 => Some(Command::BeginScope),
2 => Some(Command::EndScope),
3 => Some(Command::Pop(*iter.next()?)),
4 => Some(Command::Push(*iter.next()?)),
5 => {
let heapid = u16::from_be_bytes([*iter.next()?, *iter.next()?]);
Some(Command::AssignVariable(heapid, *iter.next()?))
}
6 => {
let heapid = u16::from_be_bytes([*iter.next()?, *iter.next()?]);
Some(Command::VarToReg(heapid, *iter.next()?))
}
7 => {
let len = u32::from_be_bytes([
*iter.next()?,
*iter.next()?,
*iter.next()?,
*iter.next()?,
]);
let string = String::from_utf8(iter.take(len as usize).cloned().collect()).ok()?;
Some(Command::StringLit(string))
}
8 => {
let num = i32::from_be_bytes([
*iter.next()?,
*iter.next()?,
*iter.next()?,
*iter.next()?,
]);
Some(Command::I32Lit(num))
}
9 => {
let funcid = u16::from_be_bytes([*iter.next()?, *iter.next()?]);
Some(Command::FunctionCall(funcid))
}
2020-07-05 21:20:49 +02:00
10 => Some(Command::Add),
11 => Some(Command::Subtract),
12 => Some(Command::Mult),
2020-07-06 11:42:38 +02:00
13 => Some(Command::Pow),
14 => Some(Command::Div),
2020-07-07 14:06:10 +02:00
15 => Some(Command::Mod),
_ => None,
}
}
2020-07-02 22:13:10 +02:00
#[cfg(feature = "compiler")]
2020-07-05 21:56:11 +02:00
fn into_u8(self) -> Vec<u8> {
let mut list = Vec::new();
list.push(self.id());
match &self {
Command::InitializeVariable(heapid, variabletype) => {
let heapid = heapid.to_be_bytes();
list.append(&mut vec![heapid[0], heapid[1], variabletype.into_u8()])
}
Command::BeginScope => (),
Command::EndScope => (),
Command::Pop(regid) => list.push(*regid),
Command::Push(regid) => list.push(*regid),
Command::AssignVariable(heapid, regid) => {
let heapid = heapid.to_be_bytes();
list.append(&mut vec![heapid[0], heapid[1], *regid]);
}
Command::VarToReg(heapid, regid) => {
let heapid = heapid.to_be_bytes();
list.append(&mut vec![heapid[0], heapid[1], *regid]);
}
Command::StringLit(string) => {
let string = string.as_bytes();
let len = (string.len() as u32).to_be_bytes();
list.append(&mut vec![len[0], len[1], len[2], len[3]]);
list.append(&mut string.to_vec());
}
Command::I32Lit(num) => {
let num = num.to_be_bytes();
list.append(&mut vec![num[0], num[1], num[2], num[3]]);
}
Command::FunctionCall(funcid) => {
let funcid = funcid.to_be_bytes();
list.append(&mut vec![funcid[0], funcid[1]]);
}
2020-07-05 21:20:49 +02:00
Command::Add => (),
Command::Subtract => (),
Command::Mult => (),
2020-07-06 11:42:38 +02:00
Command::Pow => (),
Command::Div => (),
2020-07-07 14:06:10 +02:00
Command::Mod => (),
}
list
}
}