From d0f6a042e433a94b6db0962d1b79b11ee69b78fa Mon Sep 17 00:00:00 2001 From: Savanni D'Gerinel Date: Tue, 10 Oct 2023 22:10:56 -0400 Subject: [PATCH] Set up a mock database for the sled example --- Cargo.lock | 7 +++++ Cargo.toml | 1 + build.sh | 1 + error-training/Cargo.toml | 17 +++++++++++ error-training/src/lib.rs | 62 ++++++++++++++++++++++++++++++++++++++ error-training/src/main.rs | 26 ++++++++++++++++ file-service/Cargo.toml | 2 -- 7 files changed, 114 insertions(+), 2 deletions(-) create mode 100644 error-training/Cargo.toml create mode 100644 error-training/src/lib.rs create mode 100644 error-training/src/main.rs diff --git a/Cargo.lock b/Cargo.lock index aa82149..efbd9b9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -756,6 +756,13 @@ dependencies = [ "libc", ] +[[package]] +name = "error-training" +version = "0.1.0" +dependencies = [ + "thiserror", +] + [[package]] name = "etcetera" version = "0.8.0" diff --git a/Cargo.toml b/Cargo.toml index 266bdc5..516e328 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,6 +7,7 @@ members = [ "cyberpunk-splash", "dashboard", "emseries", + "error-training", "file-service", "fluent-ergonomics", "geo-types", diff --git a/build.sh b/build.sh index 4168a1a..f3dbec5 100755 --- a/build.sh +++ b/build.sh @@ -10,6 +10,7 @@ RUST_ALL_TARGETS=( "cyberpunk-splash" "dashboard" "emseries" + "error-training" "file-service" "fluent-ergonomics" "geo-types" diff --git a/error-training/Cargo.toml b/error-training/Cargo.toml new file mode 100644 index 0000000..505c026 --- /dev/null +++ b/error-training/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "error-training" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[lib] +name = "error_training" +path = "src/lib.rs" + +[[bin]] +name = "error-training" +path = "src/main.rs" + +[dependencies] +thiserror = { version = "1" } diff --git a/error-training/src/lib.rs b/error-training/src/lib.rs new file mode 100644 index 0000000..40e23cb --- /dev/null +++ b/error-training/src/lib.rs @@ -0,0 +1,62 @@ +use thiserror::Error; + +#[derive(Clone, Debug, Error, PartialEq)] +pub enum FatalError { + #[error("Database corruption detected")] + DatabaseCorruption, +} + +#[derive(Clone, Debug, Error, PartialEq)] +pub enum MathError { + #[error("divide by zero is not defined")] + DivideByZero, + + #[error("result exceeds maxint")] + ExceedsMaxint, + + #[error("result exceeds minint")] + ExceedsMinint, +} + +#[derive(Clone, Debug, Error, PartialEq)] +pub enum DatabaseError { + #[error("value not found")] + NotFound, +} + +pub mod sled { + //! Sled-style error handling is based on Result, FatalError>. + //! FatalErrors do not get resolved. LocalErrors get bubbled up until they can be handled. + + use super::*; + use std::collections::HashMap; + + pub struct DB(HashMap); + + impl DB { + pub fn new(lst: Vec<(String, i8)>) -> Self { + Self(lst.into_iter().collect::>()) + } + + /// Retrieve a value from the database. Throw a fatal error with the "fail" key, but + /// otherwise return either the value or DatabaseError::NotFound. + /// + /// ```rust + /// use error_training::{*, sled::*}; + /// + /// let db = DB::new(vec![("a".to_owned(), 15), ("b".to_owned(), 0)]); + /// assert_eq!(db.get("fail"), Err(FatalError::DatabaseCorruption)); + /// assert_eq!(db.get("a"), Ok(Ok(15))); + /// assert_eq!(db.get("c"), Ok(Err(DatabaseError::NotFound))); + /// ``` + pub fn get(&self, key: &str) -> Result, FatalError> { + if key == "fail" { + Err(FatalError::DatabaseCorruption) + } else { + Ok(self.0.get(key).copied().ok_or(DatabaseError::NotFound)) + } + } + } + + pub fn run() {} +} diff --git a/error-training/src/main.rs b/error-training/src/main.rs new file mode 100644 index 0000000..f736691 --- /dev/null +++ b/error-training/src/main.rs @@ -0,0 +1,26 @@ +//! Error handling practice. +//! +//! The purpose of this crate is to demonstrate error handling in a couple of different scenarios +//! so that I have clear templates to refer when doing development, instead of hand-waving or +//! putting error handling off into the unspecified future. +//! +//! I am going to demonstrate error handling in the style of [Error Handling in a +//! Correctness-Critical Rust Project | sled-rs.github.io](https://sled.rs/errors.html) and in my +//! reformulation of it using Flow. +//! +//! I will also test out additional libraries in the same scenarios: +//! +//! - anyhow +//! +//! A database exists with some numbers. Mathmatical calculations will be performed on those +//! numbers. Some calculations are invalid and should fail. In some cases, those should be reported +//! to the user, and in other cases those can be recovered. Sometimes a calculation needs to be +//! performed on a value that doesn't exist, which is also a failure. However, sometimes, the +//! database will detect corruption, wich is fatal and should terminate the "app". +//! +//! In these scenarios, the "app" is a top-level function which runs the scenario. This particular +//! app should never crash, just show where crashes would happen. + +fn main() { + println!("Hello, world!"); +} diff --git a/file-service/Cargo.toml b/file-service/Cargo.toml index 0a841e3..e71b27d 100644 --- a/file-service/Cargo.toml +++ b/file-service/Cargo.toml @@ -18,8 +18,6 @@ path = "src/main.rs" name = "auth-cli" path = "src/bin/cli.rs" -[target.auth-cli.dependencies] - [dependencies] base64ct = { version = "1", features = [ "alloc" ] } build_html = { version = "2" }