From ec8802456cedd3f356ec4cca1c911ce22607ddcc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=B6khan=20=C5=9Eim=C5=9Fek?= Date: Thu, 14 Dec 2023 12:22:21 +0300 Subject: [PATCH] How to implement MyError - a String wrapper, convertible to String, and implements Error trait --- src/error_handling.rs | 58 +++++++++++++++++++++++++++++++++++++++++++ src/temp.rs | 5 ++-- 2 files changed, 61 insertions(+), 2 deletions(-) diff --git a/src/error_handling.rs b/src/error_handling.rs index 1030eeb..c116df6 100644 --- a/src/error_handling.rs +++ b/src/error_handling.rs @@ -18,6 +18,10 @@ //// or unwrap at all - they are all the same in the sense they stop the program) //// for recoverable errors. For unrecoverable, we should exit/panic. +// Good srcs: +// https://doc.rust-lang.org/book/ch09-00-error-handling.html +// https://www.lurklurk.org/effective-rust/errors.html + // ----------------------------------------- //// A. Returning multi-type error @@ -122,3 +126,57 @@ fn ex_b_3() { let _yy = xx.unwrap(); // panics with `: emergency failure` } + + + +//// C. How to implement MyError a String wrapper, convertible to String, and +//// implements Error trait + +// a. String in Result doesn't implement Error, which we'd prefer +// so that other areas of code can work with it +pub fn find_user_a(username: &str) -> Result { + let _file = std::fs::File::open("/etc/passwd") + .map_err(|e| format!("Failed to open password file: {:?}", e))?; + Ok(42) +} +// So, we use newtype pattern +// (It's not possible to impl Error for String, because neither the trait +// nor the type belong to us - the so-called orphan rule) +// | +// v +#[derive(Debug)] +pub struct MyError_(String); +impl std::error::Error for MyError_ {} + +// Error trait requires Debug + Display traits +impl std::fmt::Display for MyError_ { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.0) + } +} + +// b. We want this to work: String to MyError_ auto conversion +pub fn find_user_b(username: &str) -> Result { + let _file = std::fs::File::open("/etc/aaa") + .map_err(|e| format!("Failed to open file: {:?}", e))?; + Ok(42) +} +// error: +// the trait `From` is not implemented for `temp::MyError_` +// | +// v +impl From for MyError_ { + fn from(value: String) -> Self { + Self(value) + } +} + +#[test] +fn ex_c_1() { + let res = find_user_b("aaa"); + println!("-- res: {:?}", res); + // -- res: Err(MyError_("Failed to open file: + // Os { code: 2, kind: NotFound, message: \"No such file or directory\" }")) + + assert_eq!(res.is_err(), true); +} diff --git a/src/temp.rs b/src/temp.rs index da453b1..3ba3e4a 100644 --- a/src/temp.rs +++ b/src/temp.rs @@ -1,5 +1,6 @@ // Template - copy and change this: // -// #[test] fn ex1_ww() { +// #[test] +// fn ex1_ww() { // assert_eq!(32,32); -// } \ No newline at end of file +// }