vm_value 0.4.3

Core value trait used by fn_vm, this crate is meant to provide the building blocks to creating pass by value VMs in rust.
Documentation

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 {
    // Special case for i8
    ($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)*);
    };
    // General case for other types
    ($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)*);
    };
    // Base case to end recursion
    () => {};
}

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
}