use std::fmt::{Debug, Display};
use std::ops::{Add, BitAnd, BitOr, BitXor, Div, Mul, Neg, Not, Rem, Shl, Shr, Sub};
use small_len::{Length, SmallLength};
pub mod vm_value;
pub use vm_value::vm_str::VmStr;
pub use small_len::{length_to_bytes, length_from_bytes};
pub struct VMStatus<O, V> {
pub done: bool,
pub last_command: O,
pub value: Option<V>,
}
pub trait VM<Op, Val, T: VMValue<Op, Val, T>> {
type Error;
fn run(&mut self) -> Result<VMStatus<Op, Val>, Self::Error>;
fn execute(&mut self) -> Result<(), Self::Error>;
fn next_len(&mut self) -> Length {
self.next_small_len().into()
}
fn next_small_len(&mut self) -> SmallLength {
let u8 = self.next_byte();
match u8 {
253 => SmallLength::Word(u16::from_be_bytes(self.next_n_bytes::<2>())),
254 => SmallLength::Double(u32::from_be_bytes(self.next_n_bytes::<4>())),
255 => SmallLength::Quad(u64::from_be_bytes(self.next_n_bytes::<8>())),
_ => {
u8.into()
}
}
}
fn next_byte(&mut self) -> u8;
fn next_str(&mut self) -> String {
let len = self.next_len();
let bytes = self.next_n_bytes_vec(len);
std::str::from_utf8(&bytes).unwrap().to_string()
}
fn next_n_bytes<const N: usize>(&mut self) -> [u8; N];
fn next_n_bytes_vec(&mut self, n: Length) -> Vec<u8>;
}
pub trait Logical: Clone + Sized {
fn bool_and(&self, b: &Self) -> bool;
fn bool_or(&self, b: &Self) -> bool;
fn bool_xor(&self, b: &Self) -> bool;
fn bool_not(&self) -> bool;
fn logical_and(&self, b: &Self) -> Self {
if self.bool_and(b) {
self.clone()
} else {
b.clone()
}
}
fn logical_or(&self, b: &Self) -> Self {
if self.bool_or(b) {
self.clone()
} else {
b.clone()
}
}
fn logical_xor(&self, b: &Self) -> Self {
if self.bool_xor(b) {
self.clone()
} else {
b.clone()
}
}
fn bitwise_reverse(&self) -> Self;
}
pub trait VMValue<Op, Val, T: VMValue<Op, Val, T>>: Display + Debug + Clone + PartialEq + Logical + Add<Output=T> + Mul<Output=T> + Div<Output=T> + PartialOrd + Sub<Output=T> + BitAnd<Output=T> + BitOr<Output=T> + BitXor<Output=T> + Rem<Output=T> + Not<Output=T> + Neg<Output=T> + Shr<Output=T> + Shl<Output=T> {
fn create_from_vm_bytes<V: VM<Op, Val, T>>(vm: &mut V) -> T;
fn to_vm_bytes(&self) -> Vec<u8>;
}
pub fn str_to_vm_bytes(str: &str) -> Vec<u8> {
let bytes = str.as_bytes();
let len: Length = bytes.len().into();
let mut result = len.to_be_bytes();
result.extend(bytes);
result
}