use small_len::SmallLen;
use var_num::{VarFloat, VarInt, VarNum, VarUInt};
use crate::{length_to_bytes, Logical, VM, VMValue};
#[macro_export]
macro_rules! impl_logical_for_num {
($($t:ty),*) => {
$(
impl Logical for $t {
fn bool_and(&self, b: &Self) -> bool {
self.is_zero() && b.is_zero()
}
fn bool_or(&self, b: &Self) -> bool {
self.is_zero() || b.is_zero()
}
fn bool_xor(&self, b: &Self) -> bool {
self.is_zero() ^ b.is_zero()
}
fn bool_not(&self) -> bool {
self.is_non_zero()
}
fn bitwise_reverse(&self) -> Self {
self.reverse()
}
}
)*
}
}
impl_logical_for_num!(VarUInt, VarInt, VarFloat, VarNum);
macro_rules! impl_vm_value_for_num {
($($t:ty),*) => {
$(
impl <Op, Val> VMValue<Op, Val, $t> for $t {
fn create_from_vm_bytes<V: VM<Op, Val, $t>>(vm: &mut V) -> $t {
let len = vm.next_len();
let bytes = vm.next_n_bytes_vec(len);
<$t>::from_bytes(bytes)
}
fn to_vm_bytes(&self) -> Vec<u8> {
let bytes = self.to_bytes();
let mut r = length_to_bytes(&bytes.small_len());
r.extend(bytes);
r
}
}
)*
}
}
impl_vm_value_for_num!(VarUInt, VarInt, VarFloat);
impl <Op, Val> VMValue<Op, Val, VarNum> for VarNum {
fn create_from_vm_bytes<V: VM<Op, Val, VarNum>>(vm: &mut V) -> VarNum {
let byte = vm.next_byte();
let len = vm.next_len();
let bytes = vm.next_n_bytes_vec(len);
match byte {
0 => VarNum::Int(VarInt::from_bytes(bytes)),
1 => VarNum::UInt(VarUInt::from_bytes(bytes)),
2 => VarNum::Float(VarFloat::from_bytes(bytes)),
b => panic!("Unsupported byte: {}", b)
}
}
fn to_vm_bytes(&self) -> Vec<u8> {
let mut r = vec![];
match self {
VarNum::Int(i) => {
r.push(0);
r.extend(i.to_bytes());
}
VarNum::UInt(u) => {
r.push(1);
r.extend(u.to_bytes());
}
VarNum::Float(f) => {
r.push(2);
r.extend(f.to_bytes());
}
}
r
}
}