use crate::{Logical, VM, VMValue};
pub mod vm_str;
pub mod number;
macro_rules! impl_logical_for {
($($size:literal: $($type:ty),*)*) => {
$(
$(
impl Logical for $type {
fn bool_and(&self, b: &$type) -> bool {
(*self > 0) && (*b > 0)
}
fn bool_or(&self, b: &$type) -> bool {
(*self > 0) || (*b > 0)
}
fn bool_xor(&self, b: &$type) -> bool {
(*self > 0) ^ (*b > 0)
}
fn bool_not(&self) -> bool {
*self == 0
}
fn bitwise_reverse(&self) -> $type {
self.reverse_bits()
}
}
)*
)*
};
}
macro_rules! impl_vm_value_for {
($size:literal [if: $special:literal]: $($type:ty),*; $($rest:tt)*) => {
$(
impl <Op, Val> VMValue<Op, Val, $type> for $type {
fn create_from_vm_bytes<V: VM<Op, Val, $type>>(vm: &mut V) -> $type {
let u8 = vm.next_byte() as $type;
match u8 {
$special => panic!("Invalid byte for {}", stringify!($type)),
_ => u8.into()
}
}
fn to_vm_bytes(&self) -> Vec<u8> {
if *self <= $special as $type {
(*self as $type).to_be_bytes().to_vec()
} else {
(self.to_be() as u16).to_be_bytes().to_vec()
}
}
}
)*
impl_vm_value_for!($($rest)*);
};
($size:literal ($marker:literal): $($type:ty),*; $($rest:tt)*) => {
$(
impl <Op, Val> VMValue<Op, Val, $type> for $type {
fn create_from_vm_bytes<V: VM<Op, Val, $type>>(vm: &mut V) -> $type {
let u8 = vm.next_byte();
match u8 {
$marker => {
let bytes = vm.next_n_bytes::<$size>();
<$type>::from_be_bytes(bytes)
},
_ => panic!("Unexpected byte value for {}", stringify!($type))
}
}
fn to_vm_bytes(&self) -> Vec<u8> {
let mut result = vec![$marker];
result.extend(self.to_be_bytes().to_vec());
result
}
}
)*
impl_vm_value_for!($($rest)*);
};
() => {};
}
impl_vm_value_for! {
1 [if: 123]: i8;
2 (124): i16;
4 (125): i32;
8 (126): i64, isize;
16 (127): i128;
}
impl_logical_for!{
1: i8
2: i16
4: i32
8: i64, isize
16: i128
}