From 3cb742d8637993b2c8ae35d8b4466ababf8c13a7 Mon Sep 17 00:00:00 2001 From: Savanni D'Gerinel Date: Wed, 18 Oct 2023 22:03:43 -0400 Subject: [PATCH 1/2] Rename flow to result-extended The original name has always felt awful. I understand Rust well enough now to be able to use the name Result and override the built-in Result. --- Cargo.lock | 14 ++-- Cargo.toml | 4 +- build.sh | 3 +- {flow => result-extended}/Cargo.lock | 0 {flow => result-extended}/Cargo.toml | 2 +- {flow => result-extended}/readme.md | 0 {flow => result-extended}/src/lib.rs | 114 +++++++++++++-------------- 7 files changed, 69 insertions(+), 68 deletions(-) rename {flow => result-extended}/Cargo.lock (100%) rename {flow => result-extended}/Cargo.toml (89%) rename {flow => result-extended}/readme.md (100%) rename {flow => result-extended}/src/lib.rs (65%) diff --git a/Cargo.lock b/Cargo.lock index 312bb25..aa82149 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -861,13 +861,6 @@ dependencies = [ "miniz_oxide 0.7.1", ] -[[package]] -name = "flow" -version = "0.1.0" -dependencies = [ - "thiserror", -] - [[package]] name = "fluent" version = "0.16.0" @@ -3119,6 +3112,13 @@ dependencies = [ "winreg", ] +[[package]] +name = "result-extended" +version = "0.1.0" +dependencies = [ + "thiserror", +] + [[package]] name = "rsa" version = "0.9.2" diff --git a/Cargo.toml b/Cargo.toml index 8a3c4df..266bdc5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,6 @@ members = [ "dashboard", "emseries", "file-service", - "flow", "fluent-ergonomics", "geo-types", "gm-control-panel", @@ -17,7 +16,8 @@ members = [ "kifu/core", "kifu/gtk", "memorycache", + "nom-training", + "result-extended", "screenplay", "sgf", - "nom-training", ] diff --git a/build.sh b/build.sh index ad92ff2..4168a1a 100755 --- a/build.sh +++ b/build.sh @@ -11,7 +11,6 @@ RUST_ALL_TARGETS=( "dashboard" "emseries" "file-service" - "flow" "fluent-ergonomics" "geo-types" "gm-control-panel" @@ -20,6 +19,8 @@ RUST_ALL_TARGETS=( "kifu-core" "kifu-gtk" "memorycache" + "nom-training" + "result-extended" "screenplay" "sgf" ) diff --git a/flow/Cargo.lock b/result-extended/Cargo.lock similarity index 100% rename from flow/Cargo.lock rename to result-extended/Cargo.lock diff --git a/flow/Cargo.toml b/result-extended/Cargo.toml similarity index 89% rename from flow/Cargo.toml rename to result-extended/Cargo.toml index 6f4a4f4..8be98ab 100644 --- a/flow/Cargo.toml +++ b/result-extended/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "flow" +name = "result-extended" version = "0.1.0" edition = "2021" license = "GPL-3.0-only" diff --git a/flow/readme.md b/result-extended/readme.md similarity index 100% rename from flow/readme.md rename to result-extended/readme.md diff --git a/flow/src/lib.rs b/result-extended/src/lib.rs similarity index 65% rename from flow/src/lib.rs rename to result-extended/src/lib.rs index 2bd5c92..79f0eda 100644 --- a/flow/src/lib.rs +++ b/result-extended/src/lib.rs @@ -33,9 +33,9 @@ use std::{error::Error, fmt}; /// statement. pub trait FatalError: Error {} -/// Flow represents a return value that might be a success, might be a fatal error, or +/// Result represents a return value that might be a success, might be a fatal error, or /// might be a normal handleable error. -pub enum Flow { +pub enum Result { /// The operation was successful Ok(A), /// The operation encountered a fatal error. These should be bubbled up to a level that can @@ -45,72 +45,72 @@ pub enum Flow { Err(E), } -impl Flow { +impl Result { /// Apply an infallible function to a successful value. - pub fn map(self, mapper: O) -> Flow + pub fn map(self, mapper: O) -> Result where O: FnOnce(A) -> B, { match self { - Flow::Ok(val) => Flow::Ok(mapper(val)), - Flow::Fatal(err) => Flow::Fatal(err), - Flow::Err(err) => Flow::Err(err), + Result::Ok(val) => Result::Ok(mapper(val)), + Result::Fatal(err) => Result::Fatal(err), + Result::Err(err) => Result::Err(err), } } /// Apply a potentially fallible function to a successful value. /// /// Like `Result.and_then`, the mapping function can itself fail. - pub fn and_then(self, handler: O) -> Flow + pub fn and_then(self, handler: O) -> Result where - O: FnOnce(A) -> Flow, + O: FnOnce(A) -> Result, { match self { - Flow::Ok(val) => handler(val), - Flow::Fatal(err) => Flow::Fatal(err), - Flow::Err(err) => Flow::Err(err), + Result::Ok(val) => handler(val), + Result::Fatal(err) => Result::Fatal(err), + Result::Err(err) => Result::Err(err), } } /// Map a normal error from one type to another. This is useful for converting an error from /// one type to another, especially in re-throwing an underlying error. `?` syntax does not - /// work with `Flow`, so you will likely need to use this a lot. - pub fn map_err(self, mapper: O) -> Flow + /// work with `Result`, so you will likely need to use this a lot. + pub fn map_err(self, mapper: O) -> Result where O: FnOnce(E) -> F, { match self { - Flow::Ok(val) => Flow::Ok(val), - Flow::Fatal(err) => Flow::Fatal(err), - Flow::Err(err) => Flow::Err(mapper(err)), + Result::Ok(val) => Result::Ok(val), + Result::Fatal(err) => Result::Fatal(err), + Result::Err(err) => Result::Err(mapper(err)), } } /// Provide a function to use to recover from (or simply re-throw) an error. - pub fn or_else(self, handler: O) -> Flow + pub fn or_else(self, handler: O) -> Result where - O: FnOnce(E) -> Flow, + O: FnOnce(E) -> Result, { match self { - Flow::Ok(val) => Flow::Ok(val), - Flow::Fatal(err) => Flow::Fatal(err), - Flow::Err(err) => handler(err), + Result::Ok(val) => Result::Ok(val), + Result::Fatal(err) => Result::Fatal(err), + Result::Err(err) => handler(err), } } } -/// Convert from a normal `Result` type to a `Flow` type. The error condition for a `Result` will -/// be treated as `Flow::Err`, never `Flow::Fatal`. -impl From> for Flow { - fn from(r: Result) -> Self { +/// Convert from a normal `Result` type to a `Result` type. The error condition for a `Result` will +/// be treated as `Result::Err`, never `Result::Fatal`. +impl From> for Result { + fn from(r: std::result::Result) -> Self { match r { - Ok(val) => Flow::Ok(val), - Err(err) => Flow::Err(err), + Ok(val) => Result::Ok(val), + Err(err) => Result::Err(err), } } } -impl fmt::Debug for Flow +impl fmt::Debug for Result where A: fmt::Debug, FE: fmt::Debug, @@ -118,14 +118,14 @@ where { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - Flow::Ok(val) => f.write_fmt(format_args!("Flow::Ok {:?}", val)), - Flow::Err(err) => f.write_fmt(format_args!("Flow::Err {:?}", err)), - Flow::Fatal(err) => f.write_fmt(format_args!("Flow::Fatal {:?}", err)), + Result::Ok(val) => f.write_fmt(format_args!("Result::Ok {:?}", val)), + Result::Err(err) => f.write_fmt(format_args!("Result::Err {:?}", err)), + Result::Fatal(err) => f.write_fmt(format_args!("Result::Fatal {:?}", err)), } } } -impl PartialEq for Flow +impl PartialEq for Result where A: PartialEq, FE: PartialEq, @@ -133,27 +133,27 @@ where { fn eq(&self, rhs: &Self) -> bool { match (self, rhs) { - (Flow::Ok(val), Flow::Ok(rhs)) => val == rhs, - (Flow::Err(_), Flow::Err(_)) => true, - (Flow::Fatal(_), Flow::Fatal(_)) => true, + (Result::Ok(val), Result::Ok(rhs)) => val == rhs, + (Result::Err(_), Result::Err(_)) => true, + (Result::Fatal(_), Result::Fatal(_)) => true, _ => false, } } } /// Convenience function to create an ok value. -pub fn ok(val: A) -> Flow { - Flow::Ok(val) +pub fn ok(val: A) -> Result { + Result::Ok(val) } /// Convenience function to create an error value. -pub fn error(err: E) -> Flow { - Flow::Err(err) +pub fn error(err: E) -> Result { + Result::Err(err) } /// Convenience function to create a fatal value. -pub fn fatal(err: FE) -> Flow { - Flow::Fatal(err) +pub fn fatal(err: FE) -> Result { + Result::Fatal(err) } /// Return early from the current function if the value is a fatal error. @@ -161,9 +161,9 @@ pub fn fatal(err: FE) -> Flow { macro_rules! return_fatal { ($x:expr) => { match $x { - Flow::Fatal(err) => return Flow::Fatal(err), - Flow::Err(err) => Err(err), - Flow::Ok(val) => Ok(val), + Result::Fatal(err) => return Result::Fatal(err), + Result::Err(err) => Err(err), + Result::Ok(val) => Ok(val), } }; } @@ -173,9 +173,9 @@ macro_rules! return_fatal { macro_rules! return_error { ($x:expr) => { match $x { - Flow::Ok(val) => val, - Flow::Err(err) => return Flow::Err(err), - Flow::Fatal(err) => return Flow::Fatal(err), + Result::Ok(val) => val, + Result::Err(err) => return Result::Err(err), + Result::Fatal(err) => return Result::Fatal(err), } }; } @@ -210,19 +210,19 @@ mod test { #[test] fn it_can_map_things() { - let success: Flow = ok(15); + let success: Result = ok(15); assert_eq!(ok(16), success.map(|v| v + 1)); } #[test] fn it_can_chain_success() { - let success: Flow = ok(15); + let success: Result = ok(15); assert_eq!(ok(16), success.and_then(|v| ok(v + 1))); } #[test] fn it_can_handle_an_error() { - let failure: Flow = error(Error::Error); + let failure: Result = error(Error::Error); assert_eq!( ok::(16), failure.or_else(|_| ok(16)) @@ -231,7 +231,7 @@ mod test { #[test] fn early_exit_on_fatal() { - fn ok_func() -> Flow { + fn ok_func() -> Result { let value = return_fatal!(ok::(15)); match value { Ok(_) => ok(14), @@ -239,7 +239,7 @@ mod test { } } - fn err_func() -> Flow { + fn err_func() -> Result { let value = return_fatal!(error::(Error::Error)); match value { Ok(_) => panic!("shouldn't have gotten here"), @@ -247,7 +247,7 @@ mod test { } } - fn fatal_func() -> Flow { + fn fatal_func() -> Result { return_fatal!(fatal::(FatalError::FatalError)); panic!("failed to bail"); } @@ -259,18 +259,18 @@ mod test { #[test] fn it_can_early_exit_on_all_errors() { - fn ok_func() -> Flow { + fn ok_func() -> Result { let value = return_error!(ok::(15)); assert_eq!(value, 15); ok(14) } - fn err_func() -> Flow { + fn err_func() -> Result { return_error!(error::(Error::Error)); panic!("failed to bail"); } - fn fatal_func() -> Flow { + fn fatal_func() -> Result { return_error!(fatal::(FatalError::FatalError)); panic!("failed to bail"); } -- 2.44.1 From b756e8ca81f9941c107dd9674309ab66763fa5fa Mon Sep 17 00:00:00 2001 From: Savanni D'Gerinel Date: Wed, 18 Oct 2023 22:13:11 -0400 Subject: [PATCH 2/2] Reverse the order of Error and FatalError parameters in the Result In other usage, I discovered that it's rather confusing to have the parameters in the order that they were in. It feels better to have the fatal error after the regular error. --- result-extended/src/lib.rs | 72 +++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/result-extended/src/lib.rs b/result-extended/src/lib.rs index 79f0eda..b56be5f 100644 --- a/result-extended/src/lib.rs +++ b/result-extended/src/lib.rs @@ -35,73 +35,73 @@ pub trait FatalError: Error {} /// Result represents a return value that might be a success, might be a fatal error, or /// might be a normal handleable error. -pub enum Result { +pub enum Result { /// The operation was successful Ok(A), + /// Ordinary errors. These should be handled and the application should recover gracefully. + Err(E), /// The operation encountered a fatal error. These should be bubbled up to a level that can /// safely shut the application down. Fatal(FE), - /// Ordinary errors. These should be handled and the application should recover gracefully. - Err(E), } -impl Result { +impl Result { /// Apply an infallible function to a successful value. - pub fn map(self, mapper: O) -> Result + pub fn map(self, mapper: O) -> Result where O: FnOnce(A) -> B, { match self { Result::Ok(val) => Result::Ok(mapper(val)), - Result::Fatal(err) => Result::Fatal(err), Result::Err(err) => Result::Err(err), + Result::Fatal(err) => Result::Fatal(err), } } /// Apply a potentially fallible function to a successful value. /// /// Like `Result.and_then`, the mapping function can itself fail. - pub fn and_then(self, handler: O) -> Result + pub fn and_then(self, handler: O) -> Result where - O: FnOnce(A) -> Result, + O: FnOnce(A) -> Result, { match self { Result::Ok(val) => handler(val), - Result::Fatal(err) => Result::Fatal(err), Result::Err(err) => Result::Err(err), + Result::Fatal(err) => Result::Fatal(err), } } /// Map a normal error from one type to another. This is useful for converting an error from /// one type to another, especially in re-throwing an underlying error. `?` syntax does not /// work with `Result`, so you will likely need to use this a lot. - pub fn map_err(self, mapper: O) -> Result + pub fn map_err(self, mapper: O) -> Result where O: FnOnce(E) -> F, { match self { Result::Ok(val) => Result::Ok(val), - Result::Fatal(err) => Result::Fatal(err), Result::Err(err) => Result::Err(mapper(err)), + Result::Fatal(err) => Result::Fatal(err), } } /// Provide a function to use to recover from (or simply re-throw) an error. - pub fn or_else(self, handler: O) -> Result + pub fn or_else(self, handler: O) -> Result where - O: FnOnce(E) -> Result, + O: FnOnce(E) -> Result, { match self { Result::Ok(val) => Result::Ok(val), - Result::Fatal(err) => Result::Fatal(err), Result::Err(err) => handler(err), + Result::Fatal(err) => Result::Fatal(err), } } } /// Convert from a normal `Result` type to a `Result` type. The error condition for a `Result` will /// be treated as `Result::Err`, never `Result::Fatal`. -impl From> for Result { +impl From> for Result { fn from(r: std::result::Result) -> Self { match r { Ok(val) => Result::Ok(val), @@ -110,7 +110,7 @@ impl From> for Result { } } -impl fmt::Debug for Result +impl fmt::Debug for Result where A: fmt::Debug, FE: fmt::Debug, @@ -125,7 +125,7 @@ where } } -impl PartialEq for Result +impl PartialEq for Result where A: PartialEq, FE: PartialEq, @@ -142,17 +142,17 @@ where } /// Convenience function to create an ok value. -pub fn ok(val: A) -> Result { +pub fn ok(val: A) -> Result { Result::Ok(val) } /// Convenience function to create an error value. -pub fn error(err: E) -> Result { +pub fn error(err: E) -> Result { Result::Err(err) } /// Convenience function to create a fatal value. -pub fn fatal(err: FE) -> Result { +pub fn fatal(err: FE) -> Result { Result::Fatal(err) } @@ -210,45 +210,45 @@ mod test { #[test] fn it_can_map_things() { - let success: Result = ok(15); + let success: Result = ok(15); assert_eq!(ok(16), success.map(|v| v + 1)); } #[test] fn it_can_chain_success() { - let success: Result = ok(15); + let success: Result = ok(15); assert_eq!(ok(16), success.and_then(|v| ok(v + 1))); } #[test] fn it_can_handle_an_error() { - let failure: Result = error(Error::Error); + let failure: Result = error(Error::Error); assert_eq!( - ok::(16), + ok::(16), failure.or_else(|_| ok(16)) ); } #[test] fn early_exit_on_fatal() { - fn ok_func() -> Result { - let value = return_fatal!(ok::(15)); + fn ok_func() -> Result { + let value = return_fatal!(ok::(15)); match value { Ok(_) => ok(14), Err(err) => error(err), } } - fn err_func() -> Result { - let value = return_fatal!(error::(Error::Error)); + fn err_func() -> Result { + let value = return_fatal!(error::(Error::Error)); match value { Ok(_) => panic!("shouldn't have gotten here"), Err(_) => ok(0), } } - fn fatal_func() -> Result { - return_fatal!(fatal::(FatalError::FatalError)); + fn fatal_func() -> Result { + let _ = return_fatal!(fatal::(FatalError::FatalError)); panic!("failed to bail"); } @@ -259,19 +259,19 @@ mod test { #[test] fn it_can_early_exit_on_all_errors() { - fn ok_func() -> Result { - let value = return_error!(ok::(15)); + fn ok_func() -> Result { + let value = return_error!(ok::(15)); assert_eq!(value, 15); ok(14) } - fn err_func() -> Result { - return_error!(error::(Error::Error)); + fn err_func() -> Result { + return_error!(error::(Error::Error)); panic!("failed to bail"); } - fn fatal_func() -> Result { - return_error!(fatal::(FatalError::FatalError)); + fn fatal_func() -> Result { + return_error!(fatal::(FatalError::FatalError)); panic!("failed to bail"); } -- 2.44.1