cubipods 0.1.1

A minimal EVM implemented in Rust.
Documentation
use super::utils::errors::InstructionError;
use std::str::FromStr;

pub struct Instruction<'a> {
    pub r#type: InstructionType,
    pub literal: &'a str,
}

#[derive(Clone, Debug)]
#[repr(u8)]
pub enum InstructionType {
    STOP = 0x00,
    ADD = 0x01,
    MUL = 0x02,
    SUB = 0x03,
    DIV = 0x04,
    MOD = 0x06,
    EXP = 0x0a,
    LT = 0x10,
    GT = 0x11,
    EQ = 0x14,
    ISZERO = 0x15,
    AND = 0x16,
    OR = 0x17,
    XOR = 0x18,
    NOT = 0x19,
    BYTE = 0x1a,
    KECCAK256 = 0x20,
    POP = 0x50,
    MLOAD = 0x51,
    MSTORE = 0x52,
    SLOAD = 0x54,
    SSTORE = 0x55,
    PUSH(u8),
    DUP(u8),
    SWAP(u8),
}

impl FromStr for InstructionType {
    type Err = InstructionError;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let tmp = u128::from_str_radix(s, 16).unwrap();
        match tmp {
            0x00 => Ok(InstructionType::STOP),
            0x01 => Ok(InstructionType::ADD),
            0x02 => Ok(InstructionType::MUL),
            0x03 => Ok(InstructionType::SUB),
            0x04 => Ok(InstructionType::DIV),
            0x06 => Ok(InstructionType::MOD),
            0x0a => Ok(InstructionType::EXP),
            0x10 => Ok(InstructionType::LT),
            0x11 => Ok(InstructionType::GT),
            0x14 => Ok(InstructionType::EQ),
            0x15 => Ok(InstructionType::ISZERO),
            0x16 => Ok(InstructionType::AND),
            0x17 => Ok(InstructionType::OR),
            0x18 => Ok(InstructionType::XOR),
            0x19 => Ok(InstructionType::NOT),
            0x1a => Ok(InstructionType::BYTE),
            0x20 => Ok(InstructionType::KECCAK256),
            0x50 => Ok(InstructionType::POP),
            0x51 => Ok(InstructionType::MLOAD),
            0x52 => Ok(InstructionType::MSTORE),
            0x54 => Ok(InstructionType::SLOAD),
            0x55 => Ok(InstructionType::SSTORE),
            0x5f..=0x7f => Ok(InstructionType::PUSH((tmp % 0x5f) as u8)),
            0x80..=0x8f => Ok(InstructionType::DUP(((tmp % 0x80) + 1) as u8)),
            0x90..=0x9f => Ok(InstructionType::SWAP(((tmp % 0x90) + 1) as u8)),
            _ => {
                let mut array = [0; 2];
                let bytes = s.as_bytes();
                let len = bytes.len().min(2);
                array[..len].copy_from_slice(&bytes[..len]);

                Err(InstructionError::InvalidInstruction(array))
            }
        }
    }
}