risc-v-disassembler 0.0.1

Decodes RISC-V instructions into a rust enum.
Documentation
use crate::DisassemblerError;
use std::fmt;

pub trait Register {
    fn as_u8(&self) -> u8;
    fn try_from_u8(value: u8) -> Result<Self, DisassemblerError>
    where
        Self: Sized;
    fn as_str(&self) -> &'static str;
}

impl Register for NumberedRegister {
    fn as_u8(&self) -> u8 {
        *self as u8
    }

    fn try_from_u8(value: u8) -> Result<Self, DisassemblerError> {
        NumberedRegister::try_from(value)
    }

    fn as_str(&self) -> &'static str {
        match self {
            NumberedRegister::x0 => "x0",
            NumberedRegister::x1 => "x1",
            NumberedRegister::x2 => "x2",
            NumberedRegister::x3 => "x3",
            NumberedRegister::x4 => "x4",
            NumberedRegister::x5 => "x5",
            NumberedRegister::x6 => "x6",
            NumberedRegister::x7 => "x7",
            NumberedRegister::x8 => "x8",
            NumberedRegister::x9 => "x9",
            NumberedRegister::x10 => "x10",
            NumberedRegister::x11 => "x11",
            NumberedRegister::x12 => "x12",
            NumberedRegister::x13 => "x13",
            NumberedRegister::x14 => "x14",
            NumberedRegister::x15 => "x15",
            NumberedRegister::x16 => "x16",
            NumberedRegister::x17 => "x17",
            NumberedRegister::x18 => "x18",
            NumberedRegister::x19 => "x19",
            NumberedRegister::x20 => "x20",
            NumberedRegister::x21 => "x21",
            NumberedRegister::x22 => "x22",
            NumberedRegister::x23 => "x23",
            NumberedRegister::x24 => "x24",
            NumberedRegister::x25 => "x25",
            NumberedRegister::x26 => "x26",
            NumberedRegister::x27 => "x27",
            NumberedRegister::x28 => "x28",
            NumberedRegister::x29 => "x29",
            NumberedRegister::x30 => "x30",
            NumberedRegister::x31 => "x31",
        }
    }
}

impl Register for ABIRegister {
    fn as_u8(&self) -> u8 {
        *self as u8
    }

    fn try_from_u8(value: u8) -> Result<Self, DisassemblerError> {
        ABIRegister::try_from(value)
    }

    fn as_str(&self) -> &'static str {
        match self {
            ABIRegister::zero => "zero",
            ABIRegister::ra => "ra",
            ABIRegister::sp => "sp",
            ABIRegister::gp => "gp",
            ABIRegister::tp => "tp",
            ABIRegister::t0 => "t0",
            ABIRegister::t1 => "t1",
            ABIRegister::t2 => "t2",
            ABIRegister::s0 => "s0",
            ABIRegister::s1 => "s1",
            ABIRegister::a0 => "a0",
            ABIRegister::a1 => "a1",
            ABIRegister::a2 => "a2",
            ABIRegister::a3 => "a3",
            ABIRegister::a4 => "a4",
            ABIRegister::a5 => "a5",
            ABIRegister::a6 => "a6",
            ABIRegister::a7 => "a7",
            ABIRegister::s2 => "s2",
            ABIRegister::s3 => "s3",
            ABIRegister::s4 => "s4",
            ABIRegister::s5 => "s5",
            ABIRegister::s6 => "s6",
            ABIRegister::s7 => "s7",
            ABIRegister::s8 => "s8",
            ABIRegister::s9 => "s9",
            ABIRegister::s10 => "s10",
            ABIRegister::s11 => "s11",
            ABIRegister::t3 => "t3",
            ABIRegister::t4 => "t4",
            ABIRegister::t5 => "t5",
            ABIRegister::t6 => "t6",
        }
    }
}

#[derive(Debug, PartialEq, Clone, Copy)]
#[repr(u8)]
#[allow(non_camel_case_types)]
pub enum NumberedRegister {
    x0 = 0,
    x1 = 1,
    x2 = 2,
    x3 = 3,
    x4 = 4,
    x5 = 5,
    x6 = 6,
    x7 = 7,
    x8 = 8,
    x9 = 9,
    x10 = 10,
    x11 = 11,
    x12 = 12,
    x13 = 13,
    x14 = 14,
    x15 = 15,
    x16 = 16,
    x17 = 17,
    x18 = 18,
    x19 = 19,
    x20 = 20,
    x21 = 21,
    x22 = 22,
    x23 = 23,
    x24 = 24,
    x25 = 25,
    x26 = 26,
    x27 = 27,
    x28 = 28,
    x29 = 29,
    x30 = 30,
    x31 = 31,
}

#[derive(Debug, PartialEq, Clone, Copy)]
#[repr(u8)]
#[allow(non_camel_case_types)]
pub enum ABIRegister {
    zero = 0,
    ra = 1,
    sp = 2,
    gp = 3,
    tp = 4,
    t0 = 5,
    t1 = 6,
    t2 = 7,
    s0 = 8,
    s1 = 9,
    a0 = 10,
    a1 = 11,
    a2 = 12,
    a3 = 13,
    a4 = 14,
    a5 = 15,
    a6 = 16,
    a7 = 17,
    s2 = 18,
    s3 = 19,
    s4 = 20,
    s5 = 21,
    s6 = 22,
    s7 = 23,
    s8 = 24,
    s9 = 25,
    s10 = 26,
    s11 = 27,
    t3 = 28,
    t4 = 29,
    t5 = 30,
    t6 = 31,
}

impl TryFrom<u8> for NumberedRegister {
    type Error = DisassemblerError;

    fn try_from(value: u8) -> Result<Self, Self::Error> {
        match value {
            0 => Ok(NumberedRegister::x0),
            1 => Ok(NumberedRegister::x1),
            2 => Ok(NumberedRegister::x2),
            3 => Ok(NumberedRegister::x3),
            4 => Ok(NumberedRegister::x4),
            5 => Ok(NumberedRegister::x5),
            6 => Ok(NumberedRegister::x6),
            7 => Ok(NumberedRegister::x7),
            8 => Ok(NumberedRegister::x8),
            9 => Ok(NumberedRegister::x9),
            10 => Ok(NumberedRegister::x10),
            11 => Ok(NumberedRegister::x11),
            12 => Ok(NumberedRegister::x12),
            13 => Ok(NumberedRegister::x13),
            14 => Ok(NumberedRegister::x14),
            15 => Ok(NumberedRegister::x15),
            16 => Ok(NumberedRegister::x16),
            17 => Ok(NumberedRegister::x17),
            18 => Ok(NumberedRegister::x18),
            19 => Ok(NumberedRegister::x19),
            20 => Ok(NumberedRegister::x20),
            21 => Ok(NumberedRegister::x21),
            22 => Ok(NumberedRegister::x22),
            23 => Ok(NumberedRegister::x23),
            24 => Ok(NumberedRegister::x24),
            25 => Ok(NumberedRegister::x25),
            26 => Ok(NumberedRegister::x26),
            27 => Ok(NumberedRegister::x27),
            28 => Ok(NumberedRegister::x28),
            29 => Ok(NumberedRegister::x29),
            30 => Ok(NumberedRegister::x30),
            31 => Ok(NumberedRegister::x31),
            _ => Err(DisassemblerError::InvalidRegister(value)),
        }
    }
}

impl TryFrom<u8> for ABIRegister {
    type Error = DisassemblerError;

    fn try_from(value: u8) -> Result<Self, Self::Error> {
        match value {
            0 => Ok(ABIRegister::zero),
            1 => Ok(ABIRegister::ra),
            2 => Ok(ABIRegister::sp),
            3 => Ok(ABIRegister::gp),
            4 => Ok(ABIRegister::tp),
            5 => Ok(ABIRegister::t0),
            6 => Ok(ABIRegister::t1),
            7 => Ok(ABIRegister::t2),
            8 => Ok(ABIRegister::s0),
            9 => Ok(ABIRegister::s1),
            10 => Ok(ABIRegister::a0),
            11 => Ok(ABIRegister::a1),
            12 => Ok(ABIRegister::a2),
            13 => Ok(ABIRegister::a3),
            14 => Ok(ABIRegister::a4),
            15 => Ok(ABIRegister::a5),
            16 => Ok(ABIRegister::a6),
            17 => Ok(ABIRegister::a7),
            18 => Ok(ABIRegister::s2),
            19 => Ok(ABIRegister::s3),
            20 => Ok(ABIRegister::s4),
            21 => Ok(ABIRegister::s5),
            22 => Ok(ABIRegister::s6),
            23 => Ok(ABIRegister::s7),
            24 => Ok(ABIRegister::s8),
            25 => Ok(ABIRegister::s9),
            26 => Ok(ABIRegister::s10),
            27 => Ok(ABIRegister::s11),
            28 => Ok(ABIRegister::t3),
            29 => Ok(ABIRegister::t4),
            30 => Ok(ABIRegister::t5),
            31 => Ok(ABIRegister::t6),
            _ => Err(DisassemblerError::InvalidRegister(value)),
        }
    }
}

impl fmt::Display for NumberedRegister {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "x{}", *self as u8)
    }
}

impl fmt::Display for ABIRegister {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            ABIRegister::zero => write!(f, "zero"),
            ABIRegister::ra => write!(f, "ra"),
            ABIRegister::sp => write!(f, "sp"),
            ABIRegister::gp => write!(f, "gp"),
            ABIRegister::tp => write!(f, "tp"),
            ABIRegister::t0 => write!(f, "t0"),
            ABIRegister::t1 => write!(f, "t1"),
            ABIRegister::t2 => write!(f, "t2"),
            ABIRegister::s0 => write!(f, "s0"),
            ABIRegister::s1 => write!(f, "s1"),
            ABIRegister::a0 => write!(f, "a0"),
            ABIRegister::a1 => write!(f, "a1"),
            ABIRegister::a2 => write!(f, "a2"),
            ABIRegister::a3 => write!(f, "a3"),
            ABIRegister::a4 => write!(f, "a4"),
            ABIRegister::a5 => write!(f, "a5"),
            ABIRegister::a6 => write!(f, "a6"),
            ABIRegister::a7 => write!(f, "a7"),
            ABIRegister::s2 => write!(f, "s2"),
            ABIRegister::s3 => write!(f, "s3"),
            ABIRegister::s4 => write!(f, "s4"),
            ABIRegister::s5 => write!(f, "s5"),
            ABIRegister::s6 => write!(f, "s6"),
            ABIRegister::s7 => write!(f, "s7"),
            ABIRegister::s8 => write!(f, "s8"),
            ABIRegister::s9 => write!(f, "s9"),
            ABIRegister::s10 => write!(f, "s10"),
            ABIRegister::s11 => write!(f, "s11"),
            ABIRegister::t3 => write!(f, "t3"),
            ABIRegister::t4 => write!(f, "t4"),
            ABIRegister::t5 => write!(f, "t5"),
            ABIRegister::t6 => write!(f, "t6"),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_try_from_register() {
        assert_eq!(0.try_into(), Ok(NumberedRegister::x0));
        assert_eq!(1.try_into(), Ok(NumberedRegister::x1));
        assert_eq!(2.try_into(), Ok(NumberedRegister::x2));
        assert_eq!(3.try_into(), Ok(NumberedRegister::x3));
        assert_eq!(4.try_into(), Ok(NumberedRegister::x4));
        assert_eq!(5.try_into(), Ok(NumberedRegister::x5));
        assert_eq!(6.try_into(), Ok(NumberedRegister::x6));
        assert_eq!(7.try_into(), Ok(NumberedRegister::x7));
        assert_eq!(8.try_into(), Ok(NumberedRegister::x8));
        assert_eq!(9.try_into(), Ok(NumberedRegister::x9));
        assert_eq!(10.try_into(), Ok(NumberedRegister::x10));
        assert_eq!(11.try_into(), Ok(NumberedRegister::x11));
        assert_eq!(12.try_into(), Ok(NumberedRegister::x12));
        assert_eq!(13.try_into(), Ok(NumberedRegister::x13));
        assert_eq!(14.try_into(), Ok(NumberedRegister::x14));
        assert_eq!(15.try_into(), Ok(NumberedRegister::x15));
        assert_eq!(16.try_into(), Ok(NumberedRegister::x16));
        assert_eq!(17.try_into(), Ok(NumberedRegister::x17));
        assert_eq!(18.try_into(), Ok(NumberedRegister::x18));
        assert_eq!(19.try_into(), Ok(NumberedRegister::x19));
        assert_eq!(20.try_into(), Ok(NumberedRegister::x20));
        assert_eq!(21.try_into(), Ok(NumberedRegister::x21));
        assert_eq!(22.try_into(), Ok(NumberedRegister::x22));
        assert_eq!(23.try_into(), Ok(NumberedRegister::x23));
        assert_eq!(24.try_into(), Ok(NumberedRegister::x24));
        assert_eq!(25.try_into(), Ok(NumberedRegister::x25));
        assert_eq!(26.try_into(), Ok(NumberedRegister::x26));
        assert_eq!(27.try_into(), Ok(NumberedRegister::x27));
        assert_eq!(28.try_into(), Ok(NumberedRegister::x28));
        assert_eq!(29.try_into(), Ok(NumberedRegister::x29));
        assert_eq!(30.try_into(), Ok(NumberedRegister::x30));
        assert_eq!(31.try_into(), Ok(NumberedRegister::x31));
    }

    #[test]
    fn test_try_from_abi_register() {
        assert_eq!(0.try_into(), Ok(ABIRegister::zero));
        assert_eq!(1.try_into(), Ok(ABIRegister::ra));
        assert_eq!(2.try_into(), Ok(ABIRegister::sp));
        assert_eq!(3.try_into(), Ok(ABIRegister::gp));
        assert_eq!(4.try_into(), Ok(ABIRegister::tp));
        assert_eq!(5.try_into(), Ok(ABIRegister::t0));
        assert_eq!(6.try_into(), Ok(ABIRegister::t1));
        assert_eq!(7.try_into(), Ok(ABIRegister::t2));
        assert_eq!(8.try_into(), Ok(ABIRegister::s0));
        assert_eq!(9.try_into(), Ok(ABIRegister::s1));
        assert_eq!(10.try_into(), Ok(ABIRegister::a0));
        assert_eq!(11.try_into(), Ok(ABIRegister::a1));
        assert_eq!(12.try_into(), Ok(ABIRegister::a2));
        assert_eq!(13.try_into(), Ok(ABIRegister::a3));
        assert_eq!(14.try_into(), Ok(ABIRegister::a4));
        assert_eq!(15.try_into(), Ok(ABIRegister::a5));
        assert_eq!(16.try_into(), Ok(ABIRegister::a6));
        assert_eq!(17.try_into(), Ok(ABIRegister::a7));
        assert_eq!(18.try_into(), Ok(ABIRegister::s2));
        assert_eq!(19.try_into(), Ok(ABIRegister::s3));
        assert_eq!(20.try_into(), Ok(ABIRegister::s4));
        assert_eq!(21.try_into(), Ok(ABIRegister::s5));
        assert_eq!(22.try_into(), Ok(ABIRegister::s6));
        assert_eq!(23.try_into(), Ok(ABIRegister::s7));
        assert_eq!(24.try_into(), Ok(ABIRegister::s8));
        assert_eq!(25.try_into(), Ok(ABIRegister::s9));
        assert_eq!(26.try_into(), Ok(ABIRegister::s10));
        assert_eq!(27.try_into(), Ok(ABIRegister::s11));
        assert_eq!(28.try_into(), Ok(ABIRegister::t3));
        assert_eq!(29.try_into(), Ok(ABIRegister::t4));
        assert_eq!(30.try_into(), Ok(ABIRegister::t5));
        assert_eq!(31.try_into(), Ok(ABIRegister::t6));
    }
}