feat: better error handling (introduce thiserror)

This commit is contained in:
Rotem Horesh 2025-01-09 22:19:29 +02:00
parent 0692c2325b
commit 00a8cc563c
No known key found for this signature in database
GPG Key ID: FA5492BE76A4974A
5 changed files with 51 additions and 11 deletions

25
Cargo.lock generated
View File

@ -206,7 +206,7 @@ checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43"
dependencies = [
"getrandom",
"libredox",
"thiserror",
"thiserror 1.0.69",
]
[[package]]
@ -246,6 +246,7 @@ dependencies = [
"crossterm",
"dirs",
"regex",
"thiserror 2.0.10",
]
[[package]]
@ -307,7 +308,16 @@ version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
dependencies = [
"thiserror-impl",
"thiserror-impl 1.0.69",
]
[[package]]
name = "thiserror"
version = "2.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a3ac7f54ca534db81081ef1c1e7f6ea8a3ef428d2fc069097c079443d24124d3"
dependencies = [
"thiserror-impl 2.0.10",
]
[[package]]
@ -321,6 +331,17 @@ dependencies = [
"syn",
]
[[package]]
name = "thiserror-impl"
version = "2.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e9465d30713b56a37ede7185763c3492a91be2f5fa68d958c44e41ab9248beb"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "unicode-ident"
version = "1.0.14"

View File

@ -10,4 +10,5 @@ crossterm = "0.27"
regex = "1.11"
anyhow = "1.0"
dirs = "5.0"
thiserror = "2"
# clap = { version = "4.5", features = ["derive"] }

View File

@ -6,7 +6,7 @@ use crossterm::{
terminal::DisableLineWrap,
};
use input::Input;
use persist::{Session, SessionName};
use persist::Session;
use regex::Cache as RegexCache;
use render::Render;
@ -46,7 +46,7 @@ enum Field {
TestString,
}
struct Change {
pub struct Change {
content: bool,
cursor: bool,
}

View File

@ -6,7 +6,7 @@ use replay::{App, persist::Session};
fn main() -> anyhow::Result<()> {
let session = if let Some(name) = env::args().nth(1) {
Session::fetch(name).unwrap()
Session::fetch(name)?
} else {
Session::scratch()
};

View File

@ -19,7 +19,7 @@ impl Display for SessionName {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"-- {} --",
"--- {} ---",
if let Self::Name(name) = self {
name
} else {
@ -29,10 +29,22 @@ impl Display for SessionName {
}
}
#[derive(Debug)]
#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error("session name contains invalid char: `{0}`")]
InvalidName(char),
InvalidFormat,
#[error("session file contains invalid format: {0}")]
InvalidFormat(FormatError),
}
#[derive(thiserror::Error, Debug)]
pub enum FormatError {
#[error("session file must include exactly 2 lines")]
Lines,
#[error("the cursor position and content must be separated with a `:`")]
Separator,
#[error("cursor position must be a string representation of a `usize`")]
Cursor,
}
pub struct Session {
@ -94,6 +106,8 @@ impl Session {
fn validate_name(name: &str) -> Result<(), Error> {
if let Some(idx) = name.find(INVALID_CHARS) {
// This `unwrap` is okay, because we got that index from the `find`
// method, which means it must be in the bounds of the string
Err(Error::InvalidName(name.chars().nth(idx).unwrap()))
} else {
Ok(())
@ -104,7 +118,7 @@ fn parse_session(path: &Path) -> Result<(Input, Input), Error> {
if let Ok(s) = fs::read_to_string(path) {
let lines: Vec<_> = s.split('\n').collect();
if lines.len() != 2 {
Err(Error::InvalidFormat)
Err(Error::InvalidFormat(FormatError::Lines))
} else {
let regex_query = parse_field(lines[0])?;
let test_string = parse_field(lines[1])?;
@ -128,8 +142,12 @@ fn get_path(name: &str) -> PathBuf {
}
fn parse_field(s: &str) -> Result<Input, Error> {
let (cursor, string) = s.split_once(':').ok_or(Error::InvalidFormat)?;
let cursor = cursor.parse().map_err(|_| Error::InvalidFormat)?;
let (cursor, string) = s
.split_once(':')
.ok_or(Error::InvalidFormat(FormatError::Separator))?;
let cursor = cursor
.parse()
.map_err(|_| Error::InvalidFormat(FormatError::Cursor))?;
Ok(Input {
string: string.to_owned(),
cursor,