Switch to anyhow and thiserror

This commit is contained in:
pjht 2022-10-23 17:18:32 -05:00
parent 7782b66582
commit 4aec215c9f
7 changed files with 87 additions and 109 deletions

28
Cargo.lock generated
View File

@ -20,6 +20,12 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "anyhow"
version = "1.0.66"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "216261ddc8289130e551ddcd5ce8a064710c0d064a4d2895c67151c92b5443f6"
[[package]] [[package]]
name = "arrayvec" name = "arrayvec"
version = "0.5.2" version = "0.5.2"
@ -431,6 +437,7 @@ dependencies = [
name = "m68k_emu" name = "m68k_emu"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"anyhow",
"bitvec", "bitvec",
"derive-try-from-primitive", "derive-try-from-primitive",
"elf", "elf",
@ -444,6 +451,7 @@ dependencies = [
"reedline-repl-rs", "reedline-repl-rs",
"serde", "serde",
"serde_yaml", "serde_yaml",
"thiserror",
] ]
[[package]] [[package]]
@ -809,6 +817,26 @@ version = "0.15.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "949517c0cf1bf4ee812e2e07e08ab448e3ae0d23472aee8a06c985f0c8815b16" checksum = "949517c0cf1bf4ee812e2e07e08ab448e3ae0d23472aee8a06c985f0c8815b16"
[[package]]
name = "thiserror"
version = "1.0.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "time" name = "time"
version = "0.1.44" version = "0.1.44"

View File

@ -6,6 +6,7 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
anyhow = "1.0.66"
bitvec = "1.0.0" bitvec = "1.0.0"
derive-try-from-primitive = "1.0.0" derive-try-from-primitive = "1.0.0"
elf = "0.3.1" elf = "0.3.1"
@ -19,3 +20,4 @@ paste = "1.0.9"
reedline-repl-rs = { path = "reedline-repl-rs" } reedline-repl-rs = { path = "reedline-repl-rs" }
serde = { version = "1.0.144", features = ["derive"] } serde = { version = "1.0.144", features = ["derive"] }
serde_yaml = "0.9.13" serde_yaml = "0.9.13"
thiserror = "1.0.37"

View File

@ -1,72 +0,0 @@
use crate::{disas::DisassemblyError, m68k::BusError};
use reedline_repl_rs::Error as ReplError;
use std::{fmt::Display, io, num::ParseIntError};
#[derive(Debug)]
pub enum Error {
Repl(ReplError),
InvalidCard(u8),
Bus(BusError),
InvalidPeekFormat,
InvalidPeekSize,
Disassembly(DisassemblyError<BusError>),
Misc(&'static str),
InvalidSymbolTable,
InvalidSymbolName,
Io(io::Error),
ElfParse(elf::ParseError),
}
impl From<elf::ParseError> for Error {
fn from(v: elf::ParseError) -> Self {
Self::ElfParse(v)
}
}
impl From<io::Error> for Error {
fn from(v: io::Error) -> Self {
Self::Io(v)
}
}
impl From<DisassemblyError<BusError>> for Error {
fn from(v: DisassemblyError<BusError>) -> Self {
Self::Disassembly(v)
}
}
impl From<BusError> for Error {
fn from(v: BusError) -> Self {
Self::Bus(v)
}
}
impl From<ReplError> for Error {
fn from(v: ReplError) -> Self {
Self::Repl(v)
}
}
impl From<ParseIntError> for Error {
fn from(v: ParseIntError) -> Self {
Self::Repl(v.into())
}
}
impl Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Repl(e) => e.fmt(f),
Self::InvalidCard(n) => f.write_fmt(format_args!("Card {} does not exist", n)),
Self::Bus(e) => e.fmt(f),
Self::InvalidPeekFormat => f.write_str("Invalid peek format"),
Self::InvalidPeekSize => f.write_str("Invalid peek size"),
Self::Disassembly(e) => e.fmt(f),
Self::Misc(s) => f.write_str(s),
Self::InvalidSymbolTable => f.write_str("Invalid symbol table"),
Self::InvalidSymbolName => f.write_str("Invalid symbol name"),
Self::Io(e) => e.fmt(f),
Self::ElfParse(e) => e.fmt(f),
}
}
}

View File

@ -1,5 +1,8 @@
use bitvec::prelude::*; use bitvec::prelude::*;
use std::fmt::{Debug, Display}; use std::{
error::Error,
fmt::{Debug, Display},
};
use crate::{ use crate::{
backplane::Backplane, backplane::Backplane,
@ -19,6 +22,8 @@ impl Display for BusError {
} }
} }
impl Error for BusError {}
// pub trait Bus: Debug { // pub trait Bus: Debug {
// fn read_word(&mut self, address: u32) -> Result<u16, BusError>; // fn read_word(&mut self, address: u32) -> Result<u16, BusError>;
// fn read_byte(&mut self, address: u32) -> Result<u8, BusError>; // fn read_byte(&mut self, address: u32) -> Result<u8, BusError>;

View File

@ -3,7 +3,7 @@
mod backplane; mod backplane;
mod card; mod card;
mod disas; mod disas;
mod error; // mod error;
mod instruction; mod instruction;
mod location; mod location;
mod m68k; mod m68k;
@ -16,10 +16,10 @@ mod symbol_tables;
mod term; mod term;
use crate::{ use crate::{
backplane::Backplane, backplane::Backplane,
error::Error,
location::Location, location::Location,
m68k::{BusError, M68K}, m68k::{BusError, M68K},
}; };
use anyhow::anyhow;
use disas::DisassemblyError; use disas::DisassemblyError;
use indexmap::IndexSet; use indexmap::IndexSet;
use itertools::Itertools; use itertools::Itertools;
@ -32,6 +32,7 @@ use serde::Deserialize;
use serde_yaml::Mapping; use serde_yaml::Mapping;
use std::{convert::TryFrom, fs, path::Path, process}; use std::{convert::TryFrom, fs, path::Path, process};
use symbol_tables::SymbolTables; use symbol_tables::SymbolTables;
use thiserror::Error;
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
enum PeekFormat { enum PeekFormat {
@ -61,8 +62,12 @@ impl PeekFormat {
} }
} }
#[derive(Debug, Copy, Clone, Error)]
#[error("Invalid peek format")]
struct InvalidPeekFormat;
impl TryFrom<char> for PeekFormat { impl TryFrom<char> for PeekFormat {
type Error = Error; type Error = InvalidPeekFormat;
fn try_from(value: char) -> Result<Self, Self::Error> { fn try_from(value: char) -> Result<Self, Self::Error> {
match value { match value {
@ -71,7 +76,7 @@ impl TryFrom<char> for PeekFormat {
'd' => Ok(Self::Decimal), 'd' => Ok(Self::Decimal),
'u' => Ok(Self::UnsignedDecimal), 'u' => Ok(Self::UnsignedDecimal),
'b' => Ok(Self::Binary), 'b' => Ok(Self::Binary),
_ => Err(Error::InvalidPeekFormat), _ => Err(InvalidPeekFormat),
} }
} }
} }
@ -101,15 +106,19 @@ impl PeekSize {
} }
} }
#[derive(Debug, Copy, Clone, Error)]
#[error("Invalid peek size")]
struct InvalidPeekSize;
impl TryFrom<char> for PeekSize { impl TryFrom<char> for PeekSize {
type Error = Error; type Error = InvalidPeekSize;
fn try_from(value: char) -> Result<Self, Self::Error> { fn try_from(value: char) -> Result<Self, Self::Error> {
match value { match value {
'b' => Ok(Self::Byte), 'b' => Ok(Self::Byte),
'w' => Ok(Self::Word), 'w' => Ok(Self::Word),
'l' => Ok(Self::LongWord), 'l' => Ok(Self::LongWord),
_ => Err(Error::InvalidPeekSize), _ => Err(InvalidPeekSize),
} }
} }
} }
@ -152,7 +161,7 @@ fn main() -> Result<(), ReplError> {
symbol_tables.load_table(path, true).unwrap(); symbol_tables.load_table(path, true).unwrap();
} }
} }
Repl::<_, Error>::new(EmuState { Repl::<_, anyhow::Error>::new(EmuState {
cpu: M68K::new(backplane), cpu: M68K::new(backplane),
symbol_tables, symbol_tables,
address_breakpoints: IndexSet::new(), address_breakpoints: IndexSet::new(),
@ -183,7 +192,7 @@ fn main() -> Result<(), ReplError> {
.bus_mut() .bus_mut()
.cards_mut() .cards_mut()
.get_mut(num as usize) .get_mut(num as usize)
.ok_or(Error::InvalidCard(num))? .ok_or_else(|| anyhow!("Card {} does not exist", num))?
.cmd( .cmd(
&args &args
.get_many::<String>("args") .get_many::<String>("args")
@ -318,7 +327,7 @@ fn main() -> Result<(), ReplError> {
|args, state| { |args, state| {
let fmt_str = args.get_one::<String>("fmt").unwrap(); let fmt_str = args.get_one::<String>("fmt").unwrap();
if fmt_str.len() != 2 { if fmt_str.len() != 2 {
return Err(Error::Misc("Peek format length must be 2")); return Err(anyhow!("Peek format length must be 2"));
} }
let fmt = PeekFormat::try_from(fmt_str.chars().next().unwrap())?; let fmt = PeekFormat::try_from(fmt_str.chars().next().unwrap())?;
let size = PeekSize::try_from(fmt_str.chars().nth(1).unwrap())?; let size = PeekSize::try_from(fmt_str.chars().nth(1).unwrap())?;

View File

@ -1,4 +1,5 @@
use crate::{error::Error, symbol::Symbol}; use crate::symbol::Symbol;
use anyhow::anyhow;
use elf::gabi::{STT_FILE, STT_SECTION}; use elf::gabi::{STT_FILE, STT_SECTION};
use elf::CachedReadBytes; use elf::CachedReadBytes;
use indexmap::IndexSet; use indexmap::IndexSet;
@ -21,12 +22,12 @@ impl SymbolTable {
} }
} }
pub fn read_from_file(path: &str) -> Result<Self, Error> { pub fn read_from_file(path: &str) -> anyhow::Result<Self> {
let mut cached_reader = CachedReadBytes::new(File::open(path)?); let mut cached_reader = CachedReadBytes::new(File::open(path)?);
let mut file = elf::File::open_stream(&mut cached_reader)?; let mut file = elf::File::open_stream(&mut cached_reader)?;
let (symtab, symstrtab) = file let (symtab, symstrtab) = file
.symbol_table()? .symbol_table()?
.ok_or(Error::Misc("No symbol table in file"))?; .ok_or_else(|| anyhow!("No symbol table in file"))?;
let symbols = symtab let symbols = symtab
.iter() .iter()
.skip(1) .skip(1)

View File

@ -1,9 +1,10 @@
use std::{fmt::Display, path::Path}; use std::{fmt::Display, path::Path};
use crate::{error::Error, location::Location, symbol::Symbol, symbol_table::SymbolTable}; use crate::{location::Location, symbol::Symbol, symbol_table::SymbolTable};
use indexmap::IndexMap; use indexmap::IndexMap;
use itertools::Itertools; use itertools::Itertools;
use parse_int::parse; use parse_int::parse;
use thiserror::Error;
pub struct SymbolDisplayer<'a>(&'a SymbolTables); pub struct SymbolDisplayer<'a>(&'a SymbolTables);
@ -40,6 +41,14 @@ impl Display for SymbolDisplayer<'_> {
} }
} }
#[derive(Debug, Copy, Clone, Error)]
#[error("Invalid symbol table")]
struct InvalidSymbolTable;
#[derive(Debug, Copy, Clone, Error)]
#[error("Invalid symbol name")]
struct InvalidSymbolName;
pub struct BreakpointDisplayer<'a>(&'a SymbolTables); pub struct BreakpointDisplayer<'a>(&'a SymbolTables);
impl Display for BreakpointDisplayer<'_> { impl Display for BreakpointDisplayer<'_> {
@ -75,21 +84,16 @@ impl SymbolTables {
}) })
} }
pub fn delete(&mut self, table: &str) -> Result<SymbolTable, Error> { pub fn delete(&mut self, table: &str) -> anyhow::Result<SymbolTable> {
self.tables Ok(self.tables.shift_remove(table).ok_or(InvalidSymbolTable)?)
.shift_remove(table)
.ok_or(Error::InvalidSymbolTable)
} }
pub fn set_active(&mut self, table: &str, active: bool) -> Result<(), Error> { pub fn set_active(&mut self, table: &str, active: bool) -> anyhow::Result<()> {
self.tables self.tables.get_mut(table).ok_or(InvalidSymbolTable)?.active = active;
.get_mut(table)
.ok_or(Error::InvalidSymbolTable)?
.active = active;
Ok(()) Ok(())
} }
pub fn load_table(&mut self, path: &str, append: bool) -> Result<(), Error> { pub fn load_table(&mut self, path: &str, append: bool) -> anyhow::Result<()> {
let new_table = SymbolTable::read_from_file(path)?; let new_table = SymbolTable::read_from_file(path)?;
let table_name = Path::new(&path).file_name().unwrap().to_str().unwrap(); let table_name = Path::new(&path).file_name().unwrap().to_str().unwrap();
if let Some(table) = self.tables.get_mut(table_name) { if let Some(table) = self.tables.get_mut(table_name) {
@ -105,20 +109,20 @@ impl SymbolTables {
Ok(()) Ok(())
} }
pub fn set_breakpoint(&mut self, table: &str, symbol: String) -> Result<(), Error> { pub fn set_breakpoint(&mut self, table: &str, symbol: String) -> anyhow::Result<()> {
self.tables self.tables
.get_mut(table) .get_mut(table)
.ok_or(Error::InvalidSymbolTable)? .ok_or(InvalidSymbolTable)?
.breakpoints .breakpoints
.insert(symbol); .insert(symbol);
Ok(()) Ok(())
} }
pub fn delete_breakpoint(&mut self, table: &str, symbol: &str) -> Result<bool, Error> { pub fn delete_breakpoint(&mut self, table: &str, symbol: &str) -> anyhow::Result<bool> {
Ok(self Ok(self
.tables .tables
.get_mut(table) .get_mut(table)
.ok_or(Error::InvalidSymbolTable)? .ok_or(InvalidSymbolTable)?
.breakpoints .breakpoints
.shift_remove(symbol)) .shift_remove(symbol))
} }
@ -135,16 +139,17 @@ impl SymbolTables {
self.tables.is_empty() self.tables.is_empty()
} }
pub fn get(&self, table: &str, symbol: &str) -> Result<&Symbol, Error> { pub fn get(&self, table: &str, symbol: &str) -> anyhow::Result<&Symbol> {
self.tables Ok(self
.tables
.get(table) .get(table)
.ok_or(Error::InvalidSymbolTable)? .ok_or(InvalidSymbolTable)?
.symbols .symbols
.get(symbol) .get(symbol)
.ok_or(Error::InvalidSymbolName) .ok_or(InvalidSymbolName)?)
} }
pub fn parse_location(&self, location: &str) -> Result<Location, Error> { pub fn parse_location(&self, location: &str) -> anyhow::Result<Location> {
parse::<u32>(location).map(Location::Address).or_else(|_| { parse::<u32>(location).map(Location::Address).or_else(|_| {
let (mut table_name, symbol_name) = location.split_once(':').unwrap_or(("", location)); let (mut table_name, symbol_name) = location.split_once(':').unwrap_or(("", location));
if table_name.is_empty() { if table_name.is_empty() {
@ -152,16 +157,16 @@ impl SymbolTables {
.tables .tables
.iter() .iter()
.find(|(_, table)| table.symbols.contains_key(symbol_name)) .find(|(_, table)| table.symbols.contains_key(symbol_name))
.ok_or(Error::InvalidSymbolName)? .ok_or(InvalidSymbolName)?
.0; .0;
} else if !self } else if !self
.tables .tables
.get(table_name) .get(table_name)
.ok_or(Error::InvalidSymbolTable)? .ok_or(InvalidSymbolTable)?
.symbols .symbols
.contains_key(symbol_name) .contains_key(symbol_name)
{ {
return Err(Error::InvalidSymbolName); return Err(InvalidSymbolName.into());
} }
Ok(Location::Symbol(( Ok(Location::Symbol((
table_name.to_string(), table_name.to_string(),
@ -170,7 +175,7 @@ impl SymbolTables {
}) })
} }
pub fn parse_location_address(&self, location: &str) -> Result<u32, Error> { pub fn parse_location_address(&self, location: &str) -> anyhow::Result<u32> {
self.parse_location(location).map(|l| l.addr(self)) self.parse_location(location).map(|l| l.addr(self))
} }
} }