From 4aec215c9f2a451a852bdd7365a1d5258c750ca3 Mon Sep 17 00:00:00 2001 From: pjht Date: Sun, 23 Oct 2022 17:18:32 -0500 Subject: [PATCH] Switch to anyhow and thiserror --- Cargo.lock | 28 +++++++++++++++++ Cargo.toml | 2 ++ src/error.rs | 72 -------------------------------------------- src/m68k.rs | 7 ++++- src/main.rs | 27 +++++++++++------ src/symbol_table.rs | 7 +++-- src/symbol_tables.rs | 53 +++++++++++++++++--------------- 7 files changed, 87 insertions(+), 109 deletions(-) delete mode 100644 src/error.rs diff --git a/Cargo.lock b/Cargo.lock index f5b28d8..b689c3e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -20,6 +20,12 @@ dependencies = [ "libc", ] +[[package]] +name = "anyhow" +version = "1.0.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "216261ddc8289130e551ddcd5ce8a064710c0d064a4d2895c67151c92b5443f6" + [[package]] name = "arrayvec" version = "0.5.2" @@ -431,6 +437,7 @@ dependencies = [ name = "m68k_emu" version = "0.1.0" dependencies = [ + "anyhow", "bitvec", "derive-try-from-primitive", "elf", @@ -444,6 +451,7 @@ dependencies = [ "reedline-repl-rs", "serde", "serde_yaml", + "thiserror", ] [[package]] @@ -809,6 +817,26 @@ version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" 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]] name = "time" version = "0.1.44" diff --git a/Cargo.toml b/Cargo.toml index 571dde9..22daf2b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +anyhow = "1.0.66" bitvec = "1.0.0" derive-try-from-primitive = "1.0.0" elf = "0.3.1" @@ -19,3 +20,4 @@ paste = "1.0.9" reedline-repl-rs = { path = "reedline-repl-rs" } serde = { version = "1.0.144", features = ["derive"] } serde_yaml = "0.9.13" +thiserror = "1.0.37" diff --git a/src/error.rs b/src/error.rs deleted file mode 100644 index 591ea0f..0000000 --- a/src/error.rs +++ /dev/null @@ -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), - Misc(&'static str), - InvalidSymbolTable, - InvalidSymbolName, - Io(io::Error), - ElfParse(elf::ParseError), -} - -impl From for Error { - fn from(v: elf::ParseError) -> Self { - Self::ElfParse(v) - } -} - -impl From for Error { - fn from(v: io::Error) -> Self { - Self::Io(v) - } -} - -impl From> for Error { - fn from(v: DisassemblyError) -> Self { - Self::Disassembly(v) - } -} - -impl From for Error { - fn from(v: BusError) -> Self { - Self::Bus(v) - } -} - -impl From for Error { - fn from(v: ReplError) -> Self { - Self::Repl(v) - } -} - -impl From 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), - } - } -} diff --git a/src/m68k.rs b/src/m68k.rs index 7e3c372..969a089 100644 --- a/src/m68k.rs +++ b/src/m68k.rs @@ -1,5 +1,8 @@ use bitvec::prelude::*; -use std::fmt::{Debug, Display}; +use std::{ + error::Error, + fmt::{Debug, Display}, +}; use crate::{ backplane::Backplane, @@ -19,6 +22,8 @@ impl Display for BusError { } } +impl Error for BusError {} + // pub trait Bus: Debug { // fn read_word(&mut self, address: u32) -> Result; // fn read_byte(&mut self, address: u32) -> Result; diff --git a/src/main.rs b/src/main.rs index 6832173..4f1c1c7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,7 +3,7 @@ mod backplane; mod card; mod disas; -mod error; +// mod error; mod instruction; mod location; mod m68k; @@ -16,10 +16,10 @@ mod symbol_tables; mod term; use crate::{ backplane::Backplane, - error::Error, location::Location, m68k::{BusError, M68K}, }; +use anyhow::anyhow; use disas::DisassemblyError; use indexmap::IndexSet; use itertools::Itertools; @@ -32,6 +32,7 @@ use serde::Deserialize; use serde_yaml::Mapping; use std::{convert::TryFrom, fs, path::Path, process}; use symbol_tables::SymbolTables; +use thiserror::Error; #[derive(Copy, Clone, Debug)] enum PeekFormat { @@ -61,8 +62,12 @@ impl PeekFormat { } } +#[derive(Debug, Copy, Clone, Error)] +#[error("Invalid peek format")] +struct InvalidPeekFormat; + impl TryFrom for PeekFormat { - type Error = Error; + type Error = InvalidPeekFormat; fn try_from(value: char) -> Result { match value { @@ -71,7 +76,7 @@ impl TryFrom for PeekFormat { 'd' => Ok(Self::Decimal), 'u' => Ok(Self::UnsignedDecimal), '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 for PeekSize { - type Error = Error; + type Error = InvalidPeekSize; fn try_from(value: char) -> Result { match value { 'b' => Ok(Self::Byte), 'w' => Ok(Self::Word), 'l' => Ok(Self::LongWord), - _ => Err(Error::InvalidPeekSize), + _ => Err(InvalidPeekSize), } } } @@ -152,7 +161,7 @@ fn main() -> Result<(), ReplError> { symbol_tables.load_table(path, true).unwrap(); } } - Repl::<_, Error>::new(EmuState { + Repl::<_, anyhow::Error>::new(EmuState { cpu: M68K::new(backplane), symbol_tables, address_breakpoints: IndexSet::new(), @@ -183,7 +192,7 @@ fn main() -> Result<(), ReplError> { .bus_mut() .cards_mut() .get_mut(num as usize) - .ok_or(Error::InvalidCard(num))? + .ok_or_else(|| anyhow!("Card {} does not exist", num))? .cmd( &args .get_many::("args") @@ -318,7 +327,7 @@ fn main() -> Result<(), ReplError> { |args, state| { let fmt_str = args.get_one::("fmt").unwrap(); 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 size = PeekSize::try_from(fmt_str.chars().nth(1).unwrap())?; diff --git a/src/symbol_table.rs b/src/symbol_table.rs index 4337cae..2c381a9 100644 --- a/src/symbol_table.rs +++ b/src/symbol_table.rs @@ -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::CachedReadBytes; use indexmap::IndexSet; @@ -21,12 +22,12 @@ impl SymbolTable { } } - pub fn read_from_file(path: &str) -> Result { + pub fn read_from_file(path: &str) -> anyhow::Result { let mut cached_reader = CachedReadBytes::new(File::open(path)?); let mut file = elf::File::open_stream(&mut cached_reader)?; let (symtab, symstrtab) = file .symbol_table()? - .ok_or(Error::Misc("No symbol table in file"))?; + .ok_or_else(|| anyhow!("No symbol table in file"))?; let symbols = symtab .iter() .skip(1) diff --git a/src/symbol_tables.rs b/src/symbol_tables.rs index a0fb862..9daa1ef 100644 --- a/src/symbol_tables.rs +++ b/src/symbol_tables.rs @@ -1,9 +1,10 @@ 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 itertools::Itertools; use parse_int::parse; +use thiserror::Error; 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); impl Display for BreakpointDisplayer<'_> { @@ -75,21 +84,16 @@ impl SymbolTables { }) } - pub fn delete(&mut self, table: &str) -> Result { - self.tables - .shift_remove(table) - .ok_or(Error::InvalidSymbolTable) + pub fn delete(&mut self, table: &str) -> anyhow::Result { + Ok(self.tables.shift_remove(table).ok_or(InvalidSymbolTable)?) } - pub fn set_active(&mut self, table: &str, active: bool) -> Result<(), Error> { - self.tables - .get_mut(table) - .ok_or(Error::InvalidSymbolTable)? - .active = active; + pub fn set_active(&mut self, table: &str, active: bool) -> anyhow::Result<()> { + self.tables.get_mut(table).ok_or(InvalidSymbolTable)?.active = active; 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 table_name = Path::new(&path).file_name().unwrap().to_str().unwrap(); if let Some(table) = self.tables.get_mut(table_name) { @@ -105,20 +109,20 @@ impl SymbolTables { 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 .get_mut(table) - .ok_or(Error::InvalidSymbolTable)? + .ok_or(InvalidSymbolTable)? .breakpoints .insert(symbol); Ok(()) } - pub fn delete_breakpoint(&mut self, table: &str, symbol: &str) -> Result { + pub fn delete_breakpoint(&mut self, table: &str, symbol: &str) -> anyhow::Result { Ok(self .tables .get_mut(table) - .ok_or(Error::InvalidSymbolTable)? + .ok_or(InvalidSymbolTable)? .breakpoints .shift_remove(symbol)) } @@ -135,16 +139,17 @@ impl SymbolTables { self.tables.is_empty() } - pub fn get(&self, table: &str, symbol: &str) -> Result<&Symbol, Error> { - self.tables + pub fn get(&self, table: &str, symbol: &str) -> anyhow::Result<&Symbol> { + Ok(self + .tables .get(table) - .ok_or(Error::InvalidSymbolTable)? + .ok_or(InvalidSymbolTable)? .symbols .get(symbol) - .ok_or(Error::InvalidSymbolName) + .ok_or(InvalidSymbolName)?) } - pub fn parse_location(&self, location: &str) -> Result { + pub fn parse_location(&self, location: &str) -> anyhow::Result { parse::(location).map(Location::Address).or_else(|_| { let (mut table_name, symbol_name) = location.split_once(':').unwrap_or(("", location)); if table_name.is_empty() { @@ -152,16 +157,16 @@ impl SymbolTables { .tables .iter() .find(|(_, table)| table.symbols.contains_key(symbol_name)) - .ok_or(Error::InvalidSymbolName)? + .ok_or(InvalidSymbolName)? .0; } else if !self .tables .get(table_name) - .ok_or(Error::InvalidSymbolTable)? + .ok_or(InvalidSymbolTable)? .symbols .contains_key(symbol_name) { - return Err(Error::InvalidSymbolName); + return Err(InvalidSymbolName.into()); } Ok(Location::Symbol(( table_name.to_string(), @@ -170,7 +175,7 @@ impl SymbolTables { }) } - pub fn parse_location_address(&self, location: &str) -> Result { + pub fn parse_location_address(&self, location: &str) -> anyhow::Result { self.parse_location(location).map(|l| l.addr(self)) } }