libmwemu 0.24.5

x86 32/64bits and system internals emulator, for securely emulating malware and other stuff.
Documentation
use std::convert::TryInto;

#[derive(Copy, Clone, Debug)]
pub(crate) enum ScalarKind {
    Byte,
    Word,
    Dword,
    Qword,
    Oword,
}

impl ScalarKind {
    #[inline]
    pub(crate) const fn label(self) -> &'static str {
        match self {
            ScalarKind::Byte => "byte",
            ScalarKind::Word => "word",
            ScalarKind::Dword => "dword",
            ScalarKind::Qword => "qword",
            ScalarKind::Oword => "oword",
        }
    }
}

#[derive(Copy, Clone, Debug)]
pub(crate) enum ScalarTrace {
    ReadWord,
    ReadDword,
    ReadQword,
    WriteWord,
    WriteDword,
    WriteQword,
    WriteOword,
    ForceWriteWord,
    ForceWriteDword,
    ForceWriteQword,
    ForceWriteOword,
}

impl ScalarTrace {
    #[inline]
    pub(crate) const fn label(self) -> &'static str {
        match self {
            ScalarTrace::ReadWord => "read_word",
            ScalarTrace::ReadDword => "read_dword",
            ScalarTrace::ReadQword => "read_qword",
            ScalarTrace::WriteWord => "write_word",
            ScalarTrace::WriteDword => "write_dword",
            ScalarTrace::WriteQword => "write_qword",
            ScalarTrace::WriteOword => "write_oword",
            ScalarTrace::ForceWriteWord => "force_write_word",
            ScalarTrace::ForceWriteDword => "force_write_dword",
            ScalarTrace::ForceWriteQword => "force_write_qword",
            ScalarTrace::ForceWriteOword => "force_write_oword",
        }
    }
}

pub(crate) trait LittleEndianScalar: Copy {
    const SIZE: usize;

    fn from_le_slice(bytes: &[u8]) -> Self;

    fn to_le_vec(self) -> Vec<u8>;
}

macro_rules! impl_little_endian_scalar {
    ($ty:ty, $size:expr) => {
        impl LittleEndianScalar for $ty {
            const SIZE: usize = $size;

            fn from_le_slice(bytes: &[u8]) -> Self {
                let arr: [u8; $size] = bytes.try_into().expect("incorrect length");
                <$ty>::from_le_bytes(arr)
            }

            fn to_le_vec(self) -> Vec<u8> {
                <$ty>::to_le_bytes(self).to_vec()
            }
        }
    };
}

impl_little_endian_scalar!(u8, 1);
impl_little_endian_scalar!(u16, 2);
impl_little_endian_scalar!(u32, 4);
impl_little_endian_scalar!(u64, 8);
impl_little_endian_scalar!(u128, 16);

pub(crate) fn read_le<T: LittleEndianScalar>(bytes: &[u8]) -> Option<T> {
    if bytes.len() < T::SIZE {
        return None;
    }

    Some(T::from_le_slice(&bytes[..T::SIZE]))
}