udbserver 0.3.0

Provide Unicorn emulator with a debug server
Documentation
use core::convert::TryInto;
use unicorn_engine::unicorn_const::{Arch, Mode};

mod arm;
mod arm64;
mod m68k;
mod mips;
mod ppc;
mod riscv32;
mod riscv64;
mod x64;
mod x86;

enum Endian {
    Big,
    Little,
}

pub struct RegMap {
    regs: &'static [(Option<i32>, usize)],
    len: usize,
    desc: &'static str,
}

pub struct Register {
    map: &'static RegMap,
    endian: Endian,
}

impl Register {
    pub fn new(arch: Arch, mode: Mode) -> Self {
        let map = match arch {
            Arch::ARM => &arm::REGMAP,
            Arch::ARM64 => &arm64::REGMAP,
            Arch::M68K => &m68k::REGMAP,
            Arch::MIPS => &mips::REGMAP,
            Arch::PPC => &ppc::REGMAP,
            Arch::RISCV => {
                if (mode & Mode::RISCV32).0 != 0 {
                    &riscv32::REGMAP
                } else {
                    &riscv64::REGMAP
                }
            }
            Arch::X86 => {
                if (mode & Mode::MODE_32).0 != 0 {
                    &x86::REGMAP
                } else {
                    &x64::REGMAP
                }
            }
            _ => panic!("Unknown arch"),
        };
        let endian = {
            if (mode & Mode::BIG_ENDIAN).0 != 0 {
                Endian::Big
            } else {
                Endian::Little
            }
        };
        Register { map, endian }
    }

    pub fn list(&self) -> impl Iterator<Item = (Option<i32>, usize)> + '_ {
        self.map.regs.iter().take(self.map.len).copied()
    }

    pub fn get(&self, id: usize) -> Result<(Option<i32>, usize), ()> {
        match self.map.regs.get(id) {
            Some(reg) => Ok(*reg),
            None => Err(()),
        }
    }

    pub fn read_u64(&self, bytes: &[u8]) -> u64 {
        match self.endian {
            Endian::Little => match bytes.len() {
                2 => u16::from_le_bytes(bytes.try_into().unwrap()) as u64,
                4 => u32::from_le_bytes(bytes.try_into().unwrap()) as u64,
                8 => u64::from_le_bytes(bytes.try_into().unwrap()),
                _ => panic!("Unknown length"),
            },
            Endian::Big => match bytes.len() {
                2 => u16::from_be_bytes(bytes.try_into().unwrap()) as u64,
                4 => u32::from_be_bytes(bytes.try_into().unwrap()) as u64,
                8 => u64::from_be_bytes(bytes.try_into().unwrap()),
                _ => panic!("Unknown length"),
            },
        }
    }

    pub fn write_u64(&self, val: u64, len: usize) -> Vec<u8> {
        match self.endian {
            Endian::Little => val.to_le_bytes()[..len].to_vec(),
            Endian::Big => val.to_be_bytes()[8 - len..].to_vec(),
        }
    }

    pub fn description_xml(&self) -> &'static str {
        self.map.desc
    }
}