pcode 0.1.3

Pure Rust implementation of a p-code disassembler and lifter.
Documentation
use super::seqnum::SeqNum;

use std::fmt::{self, Debug, Display};
use std::cmp::Ordering;
use std::str::FromStr;

#[repr(u8)]
#[derive(Eq, PartialEq, Hash, Copy, Clone, Debug, Default)]
pub enum AddressSpace {
    Const,
    Unique,
    Register,
    Ram,
    Stack,
    Deref,
    #[default]
    Dummy,
}

impl From<&str> for AddressSpace {
    fn from(s: &str) -> Self {
        use AddressSpace::*;
        match s {
            "ram" => Ram,
            "register" => Register,
            "const" => Const,
            "unique" => Unique,
            "stack" => Stack,
            "deref" => Deref,
            "dummy" => Dummy,
            _ => panic!("unknown space {}", s),
        }
    }
}

impl FromStr for AddressSpace {
    type Err = std::convert::Infallible;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        Ok(s.into())
    }
}

impl AddressSpace {
    pub fn is_unique(&self) -> bool {
        self == &AddressSpace::Unique
    }

    pub fn is_const(&self) -> bool {
        self == &AddressSpace::Const
    }

    pub fn is_ram(&self) -> bool {
        self == &AddressSpace::Ram
    }

    pub fn is_dummy(&self) -> bool {
        self == &AddressSpace::Dummy
    }
}

impl Display for AddressSpace {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use AddressSpace::*;
        let s = match self {
            Ram => "ram",
            Unique => "unique",
            Const => "const",
            Register => "register",
            Stack => "stack",
            Deref => "deref",
            Dummy => "DUMMY",
        };
        write!(f, "{}", s)
    }
}

#[derive(Eq, PartialEq, Hash, Copy, Clone, Default)]
pub struct Address {
    pub space: AddressSpace,
    pub offset: u64
}

impl From<&str> for Address {
    fn from(s: &str) -> Self {
        Self::ram(u64::from_str_radix(s.strip_prefix("0x").unwrap(), 16).unwrap())
    }
}

impl Address {
    pub fn adding(&self, addend: u64) -> Self {
        Self {
            space: self.space,
            offset: self.offset + addend,
        }
    }

    pub fn ram(off: u64) -> Self {
        Self {
            space: AddressSpace::Ram,
            offset: off,
        }
    }

    pub fn seq(&self) -> SeqNum {
        SeqNum {
            pc: *self,
            uniq: 0,
        }
    }
}

impl PartialOrd for Address {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl Ord for Address {
    fn cmp(&self, other: &Self) -> Ordering {
        self.offset.cmp(&other.offset)
    }
}

impl Debug for Address {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self)
    }
}

impl Display for Address {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "0x{:x}", self.offset)
    }
}