├── .github └── workflows │ ├── main.yml │ └── rust-clippy.yml ├── .gitignore ├── Cargo.toml ├── README.md ├── examples ├── basic.rs └── std_result_interop.rs └── src └── lib.rs /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: Nightly Test 2 | on: [push, pull_request] 3 | 4 | jobs: 5 | test: 6 | name: cargo test 7 | runs-on: ubuntu-latest 8 | steps: 9 | - uses: actions/checkout@v3 10 | - uses: dtolnay/rust-toolchain@nightly 11 | - run: cargo test --all-features 12 | -------------------------------------------------------------------------------- /.github/workflows/rust-clippy.yml: -------------------------------------------------------------------------------- 1 | # This workflow uses actions that are not certified by GitHub. 2 | # They are provided by a third-party and are governed by 3 | # separate terms of service, privacy policy, and support 4 | # documentation. 5 | # rust-clippy is a tool that runs a bunch of lints to catch common 6 | # mistakes in your Rust code and help improve your Rust code. 7 | # More details at https://github.com/rust-lang/rust-clippy 8 | # and https://rust-lang.github.io/rust-clippy/ 9 | 10 | name: rust-clippy analyze 11 | 12 | on: 13 | push: 14 | branches: [ main ] 15 | pull_request: 16 | # The branches below must be a subset of the branches above 17 | branches: [ main ] 18 | schedule: 19 | - cron: '29 0 * * 5' 20 | 21 | jobs: 22 | rust-clippy-analyze: 23 | name: Run rust-clippy analyzing 24 | runs-on: ubuntu-latest 25 | permissions: 26 | contents: read 27 | security-events: write 28 | steps: 29 | - name: Checkout code 30 | uses: actions/checkout@v3 31 | 32 | - name: Install Rust toolchain 33 | uses: dtolnay/rust-toolchain@nightly 34 | 35 | - name: Install required Cargo 36 | run: cargo install clippy-sarif sarif-fmt 37 | 38 | - name: Run Clippy 39 | run: 40 | cargo +nightly clippy 41 | --all-features 42 | --message-format=json | clippy-sarif | tee rust-clippy-results.sarif | sarif-fmt 43 | continue-on-error: true 44 | 45 | - name: Upload analysis results to GitHub 46 | uses: github/codeql-action/upload-sarif@v1 47 | with: 48 | sarif_file: rust-clippy-results.sarif 49 | wait-for-processing: true 50 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | /target/ 4 | 5 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 6 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 7 | Cargo.lock 8 | 9 | # These are backup files generated by rustfmt 10 | **/*.rs.bk 11 | 12 | # VS Code Workspace and other internal configs 13 | .vscode/* 14 | !.vscode/settings.json 15 | !.vscode/tasks.json 16 | !.vscode/launch.json 17 | !.vscode/extensions.json 18 | *.code-workspace 19 | 20 | # Local History for Visual Studio Code 21 | .history/ 22 | 23 | # IntelliJ folder 24 | .idea/ 25 | 26 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "woah" 3 | version = "0.4.5" 4 | description = """ 5 | A Result type that differentiates between local errors (which can be handled) 6 | and fatal errors (which cannot) 7 | """ 8 | license = "MIT OR Apache-2.0" 9 | edition = "2021" 10 | rust-version = "1.61.0" 11 | categories = ["rust-patterns"] 12 | keywords = ["result", "error-handling"] 13 | repository = "https://github.com/alilleybrinker/woah" 14 | documentation = "https://docs.rs/woah" 15 | readme = "README.md" 16 | 17 | [dependencies] 18 | # Optional, provides methods that operate on both error variants. 19 | either = { version = "1.6.1", default-features = false, optional = true } 20 | # Optional, enables serialization and deserialization of `woah::Result`. 21 | serde = { version = "1.0.137", optional = true } 22 | 23 | [features] 24 | # The most features with minimal build time / size impact. 25 | default = ["either", "std"] 26 | # Use types from the standard library. If `either` is enabled, turn on `std` for it. 27 | std = ["either?/use_std"] 28 | # Enable all nightly-only features of the crate. Enable only on a nightly Rust toolchain. 29 | nightly = [] 30 | 31 | [dev-dependencies] 32 | # Used in some example code. 33 | rand = "0.8.5" 34 | 35 | [package.metadata.docs.rs] 36 | # Turn on all features on docs.rs (documentation explains which are nightly-only) 37 | features = ['default', 'serde', 'nightly'] 38 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # `woah` 3 | 4 | ![Crates.io](https://img.shields.io/crates/v/woah) 5 | ![Crates.io](https://img.shields.io/crates/l/woah) 6 | 7 | __A `Result` that separates local errors you can handle from fatal errors you can't.__ 8 | 9 | Sometimes you want to be able to pass some errors upward without handling them, while 10 | conveniently handling other kinds of errors at a local level. You might try to do 11 | this with manual pattern-matching on a `Result`, or by constructing a 12 | `Result, FatalError>`. Instead, you can use `woah`! 13 | 14 | ## Example 15 | 16 | ```rust 17 | use woah::prelude::*; 18 | use rand::prelude::*; 19 | 20 | fn main() { 21 | match get_data() { 22 | Success(data) => println!("{}", data), 23 | LocalErr(e) => eprintln!("error: {:?}", e), 24 | FatalErr(e) => eprintln!("error: {:?}", e), 25 | } 26 | } 27 | 28 | /// Get data from an HTTP API. 29 | fn get_data() -> Result { 30 | match do_http_request()? { 31 | Ok(data) => Success(data), 32 | Err(e) => { 33 | eprintln!("error: {:?}... retrying", e); 34 | get_data() 35 | } 36 | } 37 | } 38 | 39 | /// Make an HTTP request. 40 | /// 41 | /// This is simulated with randomly returning either a time out 42 | /// or a request failure. 43 | fn do_http_request() -> Result { 44 | if random() { 45 | LocalErr(LocalError::RequestTimedOut) 46 | } else { 47 | FatalErr(FatalError::RequestFailed) 48 | } 49 | } 50 | 51 | /// Errors which can be handled. 52 | #[derive(Debug)] 53 | enum LocalError { 54 | RequestTimedOut, 55 | } 56 | 57 | /// Errors which can't be handled. 58 | #[derive(Debug)] 59 | enum FatalError { 60 | RequestFailed, 61 | } 62 | ``` 63 | 64 | ## Use 65 | 66 | __`woah` can be used on stable Rust, but it's best when used on nightly.__ 67 | 68 | On nightly, with the `nightly` feature enabled, you get access to the `Try` 69 | trait which allows use of the `?` operator to propagate fatal errors. On 70 | stable, you have to convert to and from a `std::result::Result` to use 71 | the `?` operator, which is less convenient. 72 | 73 | ## Features 74 | 75 | | Feature Name | Default? | Purpose | 76 | |:-------------|:--------|:---------| 77 | | `nightly` | No | Lets you use the `?` operator with `woah::Result`, and adds some other convenience trait impls based on unstable APIs in `std`. | 78 | | `std` | Yes | Uses `std` for imports, adds the `Termination` and `ExitCode` APIs, and if `either` is turned on, turns on `std` for `either` as well. | 79 | | `either` | Yes | Adds methods to `woah::Result` for working with `Either` | 80 | | `serde` | No | Implements `Serialize` and `Deserialize` for `woah::Result` | 81 | 82 | ## License 83 | 84 | `woah` is dual-licensed MIT or Apache 2.0. 85 | 86 | 87 | [post]: http://sled.rs/errors.html "Link to the blog post" 88 | -------------------------------------------------------------------------------- /examples/basic.rs: -------------------------------------------------------------------------------- 1 | //! A basic example of `woah` showing a simulated HTTP request. 2 | 3 | // Compile with `cargo +nightly check --examples --features=nightly` 4 | // Run with `cargo +nightly run --example basic --features=nightly` 5 | 6 | use rand::prelude::*; 7 | use std::fmt::{self, Display, Formatter}; 8 | use woah::prelude::*; 9 | 10 | // Convenience type with `LocalError` and `FatalError` filled in. 11 | type RequestResult = Result; 12 | 13 | fn main() { 14 | match get_data() { 15 | Success(data) => println!("{}", data), 16 | LocalErr(e) => eprintln!("error: {}", e), 17 | FatalErr(e) => eprintln!("error: {}", e), 18 | } 19 | } 20 | 21 | /// Get data from an HTTP API. 22 | fn get_data() -> RequestResult { 23 | match do_http_request()? { 24 | Ok(data) => Success(data), 25 | Err(e) => { 26 | eprintln!("error: {}... retrying", e); 27 | get_data() 28 | } 29 | } 30 | } 31 | 32 | /// Make an HTTP request. 33 | /// 34 | /// This is simulated with randomly returning either a time out 35 | /// or a request failure. 36 | fn do_http_request() -> RequestResult { 37 | if random() { 38 | LocalErr(LocalError::RequestTimedOut) 39 | } else { 40 | FatalErr(FatalError::RequestFailed) 41 | } 42 | } 43 | 44 | /// Errors which can be handled. 45 | #[derive(Debug)] 46 | enum LocalError { 47 | /// A request timed out. Can be handled by retrying. 48 | RequestTimedOut, 49 | } 50 | 51 | /// Errors which can't be handled. 52 | #[derive(Debug)] 53 | enum FatalError { 54 | /// The request failed. 55 | RequestFailed, 56 | } 57 | 58 | impl Display for LocalError { 59 | fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { 60 | match self { 61 | LocalError::RequestTimedOut => write!(f, "request timed out"), 62 | } 63 | } 64 | } 65 | 66 | impl Display for FatalError { 67 | fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { 68 | match self { 69 | FatalError::RequestFailed => write!(f, "request failed"), 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /examples/std_result_interop.rs: -------------------------------------------------------------------------------- 1 | //! An example of `woah` interoperating smoothly with `std::result::Result`. 2 | 3 | // Compile with `cargo +nightly check --examples --features=nightly` 4 | // Run with `cargo +nightly run --example std_result_interop --features=nightly` 5 | 6 | use std::fmt::{self, Display, Formatter}; 7 | use std::result::Result as StdResult; 8 | use woah::prelude::*; 9 | 10 | fn main() { 11 | let r1 = woah_to_std(); 12 | let r2 = std_to_woah(); 13 | 14 | eprintln!("error: {:?} (woah -> std)", r1); 15 | eprintln!("error: {:?} (std -> woah)", r2); 16 | } 17 | 18 | /// Returns a `woah::Result`. 19 | fn returns_woah_result() -> Result<(), LocalError, FatalError> { 20 | FatalErr(FatalError::RequestFailed) 21 | } 22 | 23 | /// Returns a `std::result::Result`. 24 | fn returns_std_result() -> StdResult<(), FatalError> { 25 | Err(FatalError::RequestFailed) 26 | } 27 | 28 | /// Converts a `woah::Result` to a `std::result::Result`. 29 | fn woah_to_std() -> StdResult<(), FatalError> { 30 | let _ = returns_woah_result()?; 31 | Ok(()) 32 | } 33 | 34 | /// Converts a `std::result::Result` to a `woah::Result`. 35 | fn std_to_woah() -> Result<(), LocalError, FatalError> { 36 | let _ = returns_std_result()?; 37 | Success(()) 38 | } 39 | 40 | /// Errors which can be handled. 41 | #[derive(Debug)] 42 | enum LocalError { 43 | #[allow(unused)] 44 | /// A request timed out. Can be handled by retrying. 45 | RequestTimedOut, 46 | } 47 | 48 | /// Errors which can't be handled. 49 | #[derive(Debug)] 50 | enum FatalError { 51 | /// The request failed. 52 | RequestFailed, 53 | } 54 | 55 | impl Display for LocalError { 56 | fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { 57 | match self { 58 | LocalError::RequestTimedOut => write!(f, "request timed out"), 59 | } 60 | } 61 | } 62 | 63 | impl Display for FatalError { 64 | fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { 65 | match self { 66 | FatalError::RequestFailed => write!(f, "request failed"), 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | 3 | //! `woah` is a Rust crate which provides the following type: 4 | //! 5 | //! ```text 6 | //! enum Result { 7 | //! Success(T), 8 | //! LocalErr(L), 9 | //! FatalErr(F), 10 | //! } 11 | //! ``` 12 | //! 13 | //! This type differentiates between "local errors" which can be handled and "fatal errors" which can't, to 14 | //! enable the error handling pattern described by Tyler Neely (@spacejam) in the blog post ["Error Handling 15 | //! in a Correctness-Critical Rust Project"][post]. `woah::Result` is intended to be a more ergonomic 16 | //! alternative to the `Result, FatalError>` type proposed in the post. 17 | //! 18 | //! The important thing to note is that using the question mark operator on `woah::Result` causes 19 | //! any `FatalError` to propagate up, while providing `Result` otherwise, to enable 20 | //! the local code to handle local errors without propagating them. 21 | //! 22 | //! [__For more details, read the `docs` module.__][docs] 23 | //! 24 | //! [post]: http://sled.rs/errors.html "Link to the blog post" 25 | //! [docs]: docs/index.html "Link to the docs module" 26 | 27 | #![doc(issue_tracker_base_url = "https://github.com/alilleybrinker/woah/issues/")] 28 | #![cfg_attr(not(feature = "std"), no_std)] 29 | // Turn on the `Try` trait for both code and documentation tests. 30 | #![cfg_attr(feature = "nightly", feature(try_trait_v2))] 31 | #![cfg_attr(feature = "nightly", feature(try_blocks))] 32 | #![cfg_attr(feature = "nightly", feature(control_flow_enum))] 33 | #![cfg_attr(feature = "nightly", feature(trusted_len))] 34 | #![cfg_attr(feature = "nightly", feature(never_type))] 35 | #![cfg_attr(feature = "nightly", doc(test(attr(feature(try_trait_v2)))))] 36 | #![cfg_attr(feature = "nightly", doc(test(attr(feature(try_blocks)))))] 37 | #![cfg_attr(feature = "nightly", doc(test(attr(feature(control_flow_enum)))))] 38 | #![cfg_attr(feature = "nightly", doc(test(attr(feature(trusted_len)))))] 39 | #![cfg_attr(feature = "nightly", doc(test(attr(feature(never_type)))))] 40 | // Turn on clippy lints. 41 | #![deny(clippy::all)] 42 | #![deny(clippy::cargo)] 43 | // Turn on useful warnings (make `deny` once all are resolved.) 44 | //#![warn(missing_docs)] 45 | //#![warn(missing_doc_code_examples)] 46 | //#![warn(private_doc_tests)] 47 | #![warn(missing_debug_implementations)] 48 | #![warn(missing_copy_implementations)] 49 | 50 | use crate::Result::{FatalErr, LocalErr, Success}; 51 | #[cfg(feature = "nightly")] 52 | use core::convert::Infallible; 53 | use core::convert::{From, Into}; 54 | use core::fmt::Debug; 55 | #[cfg(feature = "nightly")] 56 | use core::iter::FromIterator; 57 | #[cfg(feature = "nightly")] 58 | use core::iter::Product; 59 | #[cfg(feature = "nightly")] 60 | use core::iter::Sum; 61 | #[cfg(feature = "nightly")] 62 | use core::iter::TrustedLen; 63 | use core::iter::{DoubleEndedIterator, FusedIterator, Iterator}; 64 | #[cfg(feature = "nightly")] 65 | use core::ops::ControlFlow; 66 | use core::ops::{Deref, DerefMut}; 67 | #[cfg(feature = "nightly")] 68 | use core::ops::{FromResidual, Try}; 69 | use core::result::{Result as StdResult, Result::Err, Result::Ok}; 70 | #[cfg(feature = "either")] 71 | use either::Either::{self, Left, Right}; 72 | #[cfg(feature = "serde")] 73 | use serde::{Deserialize, Deserializer, Serialize, Serializer}; 74 | #[cfg(feature = "std")] 75 | use std::process::{ExitCode, Termination}; 76 | 77 | pub mod prelude { 78 | //! A collection of re-exports to make `woah::Result` the standard result type. 79 | //! 80 | //! This keeps `std::result::Result` available as `StdResult`, and imports additional types and traits 81 | //! to make `woah::Result` fully-featured, based on feature flags. 82 | 83 | // Replace `std::result::Result` with `woah::Result`. 84 | // 85 | // This also imports the variant names for `woah::Result`, so they can be 86 | // referenced directly. 87 | pub use crate::{Result, Result::FatalErr, Result::LocalErr, Result::Success}; 88 | pub use core::result::Result as StdResult; 89 | 90 | // Import the Try and FromResidual traits. 91 | #[cfg(feature = "nightly")] 92 | pub use core::ops::{FromResidual, Try}; 93 | 94 | // Import the ControlFlow struct. 95 | #[cfg(feature = "nightly")] 96 | pub use core::ops::ControlFlow; 97 | 98 | // Import the Termination trait. 99 | #[cfg(feature = "std")] 100 | pub use std::process::Termination; 101 | 102 | // Import the FromIterator trait. 103 | #[cfg(feature = "nightly")] 104 | pub use core::iter::FromIterator; 105 | 106 | // Import the Product trait. 107 | #[cfg(feature = "nightly")] 108 | pub use core::iter::Product; 109 | 110 | // Import the Sum trait. 111 | #[cfg(feature = "nightly")] 112 | pub use core::iter::Sum; 113 | 114 | // Import the TrustedLen trait. 115 | #[cfg(feature = "nightly")] 116 | pub use core::iter::TrustedLen; 117 | } 118 | 119 | pub mod docs { 120 | //! Documentation, including crate features and examples. 121 | //! 122 | //! ## Why are the docs like this? 123 | //! 124 | //! Putting the docs in Rustdoc means they can be run as documentation tests. Breaking them up into modules 125 | //! helps keep them from getting too unwieldy, so people can still navigate the API itself with ease. 126 | //! 127 | //! `woah::Result` has a lot of methods, and the way they're grouped and presented by Rustdoc isn't always 128 | //! easy to navigate. To help, this page explains them in groups of similar methods. 129 | //! 130 | //! [is]: #see-if-the-result-is-a-particular-variant 131 | //! [contains]: #see-if-the-result-contains-a-value 132 | //! [get]: #get-an-option-if-a-variant-is-present 133 | //! [as_ref]: #reference-the-contained-value 134 | //! [as_deref]: #dereference-the-contained-value 135 | //! [map]: #map-over-the-contained-value 136 | //! [iter]: #iterate-over-the-contained-value 137 | //! [compose]: #compose-results 138 | //! [unwrap]: #unwrap-the-result 139 | //! [clone]: #copy-or-clone-the-contained-value 140 | //! [transpose]: #transpose-when-holding-an-option 141 | //! [convert]: #convert-to-and-from-a-stdresultresult 142 | //! [try]: #use-woahresult-with-the-question-mark-operator 143 | //! [main]: #use-woahresult-as-the-return-type-of-main 144 | //! [from_iter]: #build-a-woahresult-from-an-iterator 145 | //! 146 | //! ## Methods 147 | //! 148 | //! ### See if the `Result` is a particular variant 149 | //! 150 | //! These methods, the "is" methods, return a `bool` based on what variant is present. 151 | //! 152 | //! 1. [`is_success`](../../enum.Result.html#method.is_success) 153 | //! 2. [`is_err`](../../enum.Result.html#method.is_err) 154 | //! 3. [`is_local_err`](../../enum.Result.html#method.is_local_err) 155 | //! 4. [`is_fatal_err`](../../enum.Result.html#method.is_fatal_err) 156 | //! 157 | //! ### See if the `Result` contains a value 158 | //! 159 | //! These methods check if the `Result` contains a particular value. 160 | //! 161 | //! 1. [`contains`](../../enum.Result.html#method.contains) 162 | //! 2. [`contains_err`](../../enum.Result.html#method.contains_err) 163 | //! 3. [`contains_local_err`](../../enum.Result.html#method.contains_local_err) 164 | //! 4. [`contains_fatal_err`](../../enum.Result.html#method.contains_fatal_err) 165 | //! 166 | //! ### Get an `Option` if a variant is present 167 | //! 168 | //! These methods try to get the contained value out, returning an `Option` in case it's 169 | //! another variant. 170 | //! 171 | //! 1. [`success`](../../enum.Result.html#method.success) 172 | //! 2. [`err`](../../enum.Result.html#method.err) 173 | //! 3. [`local_err`](../../enum.Result.html#method.local_err) 174 | //! 4. [`fatal_err`](../../enum.Result.html#method.fatal_err) 175 | //! 176 | //! ### Reference the contained value 177 | //! 178 | //! Gets a reference (immutable or mutable) to the contained value. 179 | //! 180 | //! 1. [`as_ref`](../../enum.Result.html#method.as_ref) 181 | //! 2. [`as_mut`](../../enum.Result.html#method.as_mut) 182 | //! 183 | //! ### Dereference the contained value 184 | //! 185 | //! Dereferences the contained value if it implements `Deref`. 186 | //! 187 | //! 1. [`as_deref`](../../enum.Result.html#method.as_deref) 188 | //! 2. [`as_deref_err`](../../enum.Result.html#method.as_deref_err) 189 | //! 3. [`as_deref_local_err`](../../enum.Result.html#method.as_deref_local_err) 190 | //! 4. [`as_deref_fatal_err`](../../enum.Result.html#method.as_deref_fatal_err) 191 | //! 192 | //! Dereferences the contained value mutably if it implements `DerefMut`. 193 | //! 194 | //! 1. [`as_deref_mut`](../../enum.Result.html#method.as_deref_mut) 195 | //! 2. [`as_deref_mut_err`](../../enum.Result.html#method.as_deref_mut_err) 196 | //! 3. [`as_deref_mut_local_err`](../../enum.Result.html#method.as_deref_mut_local_err) 197 | //! 4. [`as_deref_mut_fatal_err`](../../enum.Result.html#method.as_deref_mut_fatal_err) 198 | //! 199 | //! ### Map over the contained value 200 | //! 201 | //! Applies some function to the contained value. 202 | //! 203 | //! 1. [`map`](../../enum.Result.html#method.map) 204 | //! 2. [`map_or`](../../enum.Result.html#method.map_or) 205 | //! 3. [`map_or_else`](../../enum.Result.html#method.map_or_else) 206 | //! 207 | //! Applies some function to the contained value, if it's a local or fatal error. 208 | //! 209 | //! 1. [`map_err`](../../enum.Result.html#method.map_err) 210 | //! 2. [`map_err_or`](../../enum.Result.html#method.map_err_or) 211 | //! 3. [`map_err_or_else`](../../enum.Result.html#method.map_err_or_else) 212 | //! 213 | //! Applies some function to the contained value, if it's a local error. 214 | //! 215 | //! 1. [`map_local_err`](../../enum.Result.html#method.map_local_err) 216 | //! 2. [`map_local_err_or`](../../enum.Result.html#method.map_local_err_or) 217 | //! 3. [`map_local_err_or_else`](../../enum.Result.html#method.map_local_err_or_else) 218 | //! 219 | //! Applies some function to the contained value, if it's a fatal error. 220 | //! 221 | //! 1. [`map_fatal_err`](../../enum.Result.html#method.map_fatal_err) 222 | //! 2. [`map_fatal_err_or`](../../enum.Result.html#method.map_fatal_err_or) 223 | //! 3. [`map_fatal_err_or_else`](../../enum.Result.html#method.map_fatal_err_or_else) 224 | //! 225 | //! ### Iterate over the contained value 226 | //! 227 | //! 1. [`iter`](../../enum.Result.html#method.iter) 228 | //! 2. [`iter_mut`](../../enum.Result.html#method.iter_mut) 229 | //! 3. [`into_iter`](../../enum.Result.html#impl-IntoIterator-2) (for `woah::Result`) 230 | //! 4. [`into_iter`](../../enum.Result.html#impl-IntoIterator-1) (for `&woah::Result`) 231 | //! 5. [`into_iter`](../../enum.Result.html#impl-IntoIterator) (for `&mut woah::Result`) 232 | //! 233 | //! ### Compose `Result`s 234 | //! 235 | //! 1. [`and`](../../enum.Result.html#method.and) 236 | //! 2. [`and_then`](../../enum.Result.html#method.and_then) 237 | //! 3. [`or`](../../enum.Result.html#method.or) 238 | //! 4. [`or_else`](../../enum.Result.html#method.or_else) 239 | //! 5. [`or_else_fatal`](../../enum.Result.html#method.or_else_fatal) 240 | //! 6. [`or_else_local`](../../enum.Result.html#method.or_else_local) 241 | //! 7. [`or_fatal`](../../enum.Result.html#method.or_fatal) 242 | //! 8. [`or_local`](../../enum.Result.html#method.or_local) 243 | //! 244 | //! ### Unwrap the `Result` 245 | //! 246 | //! 1. [`unwrap`](../../enum.Result.html#method.unwrap) 247 | //! 2. [`unwrap_err`](../../enum.Result.html#method.unwrap_err) 248 | //! 3. [`unwrap_fatal_err`](../../enum.Result.html#method.unwrap_fatal_err) 249 | //! 4. [`unwrap_local_err`](../../enum.Result.html#method.unwrap_local_err) 250 | //! 5. [`unwrap_or`](../../enum.Result.html#method.unwrap_or) 251 | //! 6. [`unwrap_or_default`](../../enum.Result.html#method.unwrap_or_default) 252 | //! 7. [`unwrap_or_else`](../../enum.Result.html#method.unwrap_or_else) 253 | //! 8. [`expect`](../../enum.Result.html#method.expect) 254 | //! 9. [`expect_err`](../../enum.Result.html#method.expect_err) 255 | //! 10. [`expect_fatal_err`](../../enum.Result.html#method.expect_fatal_err) 256 | //! 11. [`expect_local_err`](../../enum.Result.html#method.expect_local_err) 257 | //! 258 | //! ### Copy or clone the contained value 259 | //! 260 | //! 1. [`cloned`](../../enum.Result.html#method.cloned) (for `&woah::Result`) 261 | //! 2. [`cloned`](../../enum.Result.html#method.cloned-1) (for `&mut woah::Result`) 262 | //! 1. [`copied`](../../enum.Result.html#method.copied) (for `&woah::Result`) 263 | //! 2. [`copied`](../../enum.Result.html#method.copied-1) (for `&mut woah::Result`) 264 | //! 265 | //! ### Transpose when holding an `Option` 266 | //! 267 | //! 1. [`transpose`](../../enum.Result.html#method.transpose) 268 | //! 269 | //! ### Convert to and from a `std::result::Result` 270 | //! 271 | //! 1. [`into_result`](../../enum.Result.html#method.into_result) 272 | //! 1. [`into_result_default`](../../enum.Result.html#method.into_result_default) 273 | //! 274 | //! ### Use `woah::Result` with the question mark operator 275 | //! 276 | //! 1. [`Try` impl](../../enum.Result.html#impl-Try) (nightly-only, with `nightly` feature or `try_trait` feature) 277 | //! 278 | //! ### Use `woah::Result` as the return type of `main` 279 | //! 280 | //! 1. [`Termination` impl](../../enum.Result.html#impl-Termination) (nightly-only, with `nightly` feature, or `termination_trait` and `std` features) 281 | //! 282 | //! ### Build a `woah::Result` from an iterator 283 | //! 284 | //! 1. [`FromIterator` impl](../../enum.Result.html#impl-FromIterator%3CResult%3CA%2C%20L%2C%20F%3E%3E) (nightly-only, with `nightly` feature, or `from_iterator_trait` feature) 285 | //! 286 | //! ## Features 287 | //! 288 | //! `woah` can be used on stable or nightly. On nightly, enabling the `nightly` feature is recommended, 289 | //! to get the full power of the `woah::Result` type, including: 290 | //! 291 | //! * Being able to use it with the question mark operator, 292 | //! * Being able to make it the return type of `fn main`, 293 | //! * Gaining a number of useful additional methods, including `from_iter` (which enables easy conversion 294 | //! from `Vec` into `woah::Result, L, F>` via the `collect` method). 295 | //! 296 | //! The following table is the full list of features. If you want to use `woah` without any dependencies, 297 | //! you can disable the `either` feature, which otherwise imports the `either` crate to add additional 298 | //! methods. 299 | //! 300 | //!| Feature Name | Channels | Depends On | What It Does | 301 | //!|:--------------|:----------------------|:-------------------|:-------------| 302 | //!| `default` | Stable, Beta, Nightly | `either` | Enables default features (currently `either` and `std`). | 303 | //!| `nightly` | Nightly | None | Enables all nightly-only features. __This feature is permanently unstable, and changes to the APIs enabled by this feature are never considered breaking changes.__ | 304 | //!| `serde` | Stable, Beta, Nightly | None | Implements `serde::Serialize` and `serde::Deserialize` for `woah::Result`. | 305 | //!| `std` | Stable, Beta, Nightly | None | Use the standard library. Turn off to make the crate `no_std` compatible. _Turning off the standard library eliminates the `Termination` trait and `ExitCode` type._ | 306 | //!| `either` | Stable, Beta, Nightly | None | Adds the `either` crate as a dependency and provides convenience methods for operating on `Either`. | 307 | //! 308 | //! 309 | //! ## Examples 310 | //! 311 | //! Examples of using `woah` on both stable and nightly. 312 | //! 313 | //! ### Example on stable 314 | //! 315 | //!``` 316 | //! use woah::prelude::*; 317 | //! use std::cmp::Ordering; 318 | //! 319 | //! match get_number() { 320 | //! Ok(num) => println!("Got a number: {}", num), 321 | //! StdResult::Err(fatal_err) => eprintln!("Fatal error: {:?}", fatal_err), 322 | //! } 323 | //! 324 | //! fn get_number() -> StdResult { 325 | //! // propagate any fatal error 326 | //! let result: StdResult = compare_numbers(5, 5)?; 327 | //! 328 | //! // handle any local error 329 | //! let num = result.unwrap_or_else(|local_err| { 330 | //! println!("Local error: {:?}", local_err); 331 | //! i64::default() 332 | //! }); 333 | //! 334 | //! Ok(num) 335 | //! } 336 | //! 337 | //! fn compare_numbers(x: i64, y: i64) -> StdResult, FatalError> { 338 | //! match x.cmp(&y) { 339 | //! Ordering::Greater => Success(x), 340 | //! Ordering::Equal => LocalErr(LocalError::SomeError), 341 | //! Ordering::Less => FatalErr(FatalError::CatastrophicError), 342 | //! }.into_result() 343 | //! } 344 | //! 345 | //! #[derive(Debug)] 346 | //! enum LocalError { SomeError, AnotherError } 347 | //! 348 | //! #[derive(Debug)] 349 | //! enum FatalError { BigBadError, CatastrophicError } 350 | //! ``` 351 | //! 352 | //! ### Example on nightly 353 | //! 354 | //! This uses `--features nightly` to enable nightly-only features. 355 | //! 356 | //! ``` 357 | //! use woah::prelude::*; 358 | //! use std::cmp::Ordering; 359 | //! 360 | //! # #[cfg(feature = "nightly")] 361 | //! # fn main() { 362 | //! match get_number() { 363 | //! Ok(num) => println!("Got a number: {}", num), 364 | //! StdResult::Err(fatal_err) => eprintln!("Fatal error: {:?}", fatal_err), 365 | //! } 366 | //! # } 367 | //! # 368 | //! # #[cfg(not(feature = "nightly"))] 369 | //! # fn main() {} 370 | //! 371 | //! # #[cfg(feature = "nightly")] 372 | //! fn get_number() -> StdResult { 373 | //! // propagate any fatal error 374 | //! let result: StdResult = compare_numbers(5, 10)?; 375 | //! 376 | //! // handle any local error 377 | //! let num = result.unwrap_or_else(|local_err| { 378 | //! println!("Local error: {:?}", local_err); 379 | //! i64::default() 380 | //! }); 381 | //! 382 | //! Ok(num) 383 | //! } 384 | //! 385 | //! # #[cfg(feature = "nightly")] 386 | //! fn compare_numbers(x: i64, y: i64) -> Result { 387 | //! match x.cmp(&y) { 388 | //! Ordering::Greater => Success(x), 389 | //! Ordering::Equal => LocalErr(LocalError::Equal), 390 | //! Ordering::Less => FatalErr(FatalError::Less), 391 | //! } 392 | //! } 393 | //! 394 | //! # #[cfg(feature = "nightly")] 395 | //! #[derive(Debug)] 396 | //! enum LocalError { Equal } 397 | //! 398 | //! # #[cfg(feature = "nightly")] 399 | //! #[derive(Debug)] 400 | //! enum FatalError { Less } 401 | //! ``` 402 | } 403 | 404 | /// A type representing success (`Success`), a local error (`LocalErr`), or a fatal error (`FatalErr`). 405 | /// 406 | /// See the [`woah`](index.html) top-level documentation for details. 407 | #[derive(Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)] 408 | #[must_use = "this `Result` may be a `LocalErr`, which should be handled, or a `FatalErr`, which should be propagated"] 409 | pub enum Result { 410 | /// Contains the success value. 411 | Success(T), 412 | /// Contains a local error value (which should be handled) 413 | LocalErr(L), 414 | /// Contains a fatal error value (which should be propagated) 415 | FatalErr(F), 416 | } 417 | 418 | #[cfg(feature = "nightly")] 419 | impl FromResidual for Result { 420 | #[inline] 421 | fn from_residual(residual: StdResult) -> Self { 422 | Result::FatalErr(residual.unwrap_err()) 423 | } 424 | } 425 | 426 | #[cfg(feature = "nightly")] 427 | impl Try for Result { 428 | type Output = StdResult; 429 | type Residual = StdResult; 430 | 431 | #[inline] 432 | fn from_output(output: StdResult) -> Self { 433 | From::from(output) 434 | } 435 | 436 | #[inline] 437 | fn branch(self) -> ControlFlow, StdResult> { 438 | match self { 439 | Result::Success(t) => ControlFlow::Continue(Ok(t)), 440 | Result::LocalErr(l) => ControlFlow::Continue(Err(l)), 441 | Result::FatalErr(f) => ControlFlow::Break(Err(f)), 442 | } 443 | } 444 | } 445 | 446 | impl Result { 447 | /// Convert `woah::Result` into a `Result, F>`, which is equivalent 448 | /// in `?` behavior. 449 | /// 450 | /// # Example 451 | /// 452 | /// ``` 453 | /// use woah::prelude::*; 454 | /// 455 | /// let result: StdResult, &str> = LocalErr("a local error").into_result(); 456 | /// assert_eq!(result, Ok(Err("a local error"))); 457 | /// ``` 458 | #[inline] 459 | pub fn into_result(self) -> StdResult, F> { 460 | self.into() 461 | } 462 | 463 | /// Construct either a [`Success`] or [`LocalErr`] variant based on a 464 | /// `Result`. 465 | /// 466 | /// [`Success`]: enum.Result.html#variant.Success 467 | /// [`LocalErr`]: enum.Result.html#variant.LocalErr 468 | /// 469 | /// # Example 470 | /// 471 | /// ``` 472 | /// use woah::prelude::*; 473 | /// 474 | /// let result: Result = Result::from_result(Ok(0)); 475 | /// assert_eq!(result, Success(0)); 476 | /// ``` 477 | #[inline] 478 | pub fn from_result(ok: StdResult) -> Self { 479 | match ok { 480 | Ok(t) => Success(t), 481 | Err(err) => LocalErr(err), 482 | } 483 | } 484 | 485 | /// Construct the [`Success`] variant based on some success value. 486 | /// 487 | /// [`Success`]: enum.Result.html#variant.Success 488 | /// 489 | /// # Example 490 | /// 491 | /// ``` 492 | /// use woah::prelude::*; 493 | /// 494 | /// let fatal_err: Result = Result::from_success(0); 495 | /// assert_eq!(fatal_err, Success(0)); 496 | /// ``` 497 | #[inline] 498 | pub fn from_success(val: T) -> Self { 499 | Success(val) 500 | } 501 | 502 | /// Construct the [`LocalErr`] variant based on some error. 503 | /// 504 | /// [`LocalErr`]: enum.Result.html#variant.LocalErr 505 | /// 506 | /// # Example 507 | /// 508 | /// ``` 509 | /// use woah::prelude::*; 510 | /// 511 | /// let fatal_err: Result = Result::from_fatal_error("a fatal error"); 512 | /// assert_eq!(fatal_err, FatalErr("a fatal error")); 513 | /// ``` 514 | #[inline] 515 | pub fn from_local_err(err: L) -> Self { 516 | LocalErr(err) 517 | } 518 | 519 | /// Construct the [`FatalErr`] variant based on some error. 520 | /// 521 | /// [`FatalErr`]: enum.Result.html#variant.FatalErr 522 | /// 523 | /// # Example 524 | /// 525 | /// ``` 526 | /// use woah::prelude::*; 527 | /// 528 | /// let fatal_err: Result = Result::from_fatal_error("a fatal error"); 529 | /// assert_eq!(fatal_err, FatalErr("a fatal error")); 530 | /// ``` 531 | #[inline] 532 | pub fn from_fatal_error(err: F) -> Self { 533 | FatalErr(err) 534 | } 535 | 536 | /// Returns `true` if the result is [`Success`]. 537 | /// 538 | /// [`Success`]: enum.Result.html#variant.Success 539 | /// 540 | /// # Example 541 | /// 542 | /// ``` 543 | /// use woah::prelude::*; 544 | /// 545 | /// let x: Result = Success(-3); 546 | /// assert_eq!(x.is_success(), true); 547 | /// 548 | /// let x: Result = LocalErr("Some error message"); 549 | /// assert_eq!(x.is_success(), false); 550 | /// 551 | /// let x: Result = FatalErr("Another error message"); 552 | /// assert_eq!(x.is_success(), false); 553 | /// ``` 554 | #[must_use = "if you intended to assert that this is ok, consider `.unwrap()` instead"] 555 | #[inline] 556 | pub fn is_success(&self) -> bool { 557 | matches!(self, Success(_)) 558 | } 559 | 560 | /// Returns `true` if the result is [`LocalErr`] or [`FatalErr`]. 561 | /// 562 | /// [`LocalErr`]: enum.Result.html#variant.LocalErr 563 | /// [`FatalErr`]: enum.Result.html#variant.FatalErr 564 | /// 565 | /// # Example 566 | /// 567 | /// ``` 568 | /// use woah::prelude::*; 569 | /// 570 | /// let x: Result = Success(-3); 571 | /// assert_eq!(x.is_err(), false); 572 | /// 573 | /// let x: Result = LocalErr("Some error message"); 574 | /// assert_eq!(x.is_err(), true); 575 | /// 576 | /// let x: Result = FatalErr("Another error message"); 577 | /// assert_eq!(x.is_err(), true); 578 | /// ``` 579 | #[must_use = "if you intended to assert that this is err, consider `.unwrap_err()` instead"] 580 | #[inline] 581 | pub fn is_err(&self) -> bool { 582 | !self.is_success() 583 | } 584 | 585 | /// Returns `true` if the result is [`LocalErr`]. 586 | /// 587 | /// [`LocalErr`]: enum.Result.html#variant.LocalErr 588 | /// 589 | /// # Example 590 | /// 591 | /// ``` 592 | /// use woah::prelude::*; 593 | /// 594 | /// let x: Result = Success(-3); 595 | /// assert_eq!(x.is_local_err(), false); 596 | /// 597 | /// let x: Result = LocalErr("Some error message"); 598 | /// assert_eq!(x.is_local_err(), true); 599 | /// 600 | /// let x: Result = FatalErr("Another error message"); 601 | /// assert_eq!(x.is_local_err(), false); 602 | /// ``` 603 | #[must_use = "if you intended to assert that this is local_err, consider `.unwrap_local_err()` instead"] 604 | #[inline] 605 | pub fn is_local_err(&self) -> bool { 606 | matches!(self, LocalErr(_)) 607 | } 608 | 609 | /// Returns `true` if the result is [`FatalErr`]. 610 | /// 611 | /// [`FatalErr`]: enum.Result.html#variant.FatalErr 612 | /// 613 | /// # Example 614 | /// 615 | /// ``` 616 | /// use woah::prelude::*; 617 | /// 618 | /// let x: Result = Success(-3); 619 | /// assert_eq!(x.is_fatal_err(), false); 620 | /// 621 | /// let x: Result = LocalErr("Some error message"); 622 | /// assert_eq!(x.is_fatal_err(), false); 623 | /// 624 | /// let x: Result = FatalErr("Another error message"); 625 | /// assert_eq!(x.is_fatal_err(), true); 626 | /// ``` 627 | #[must_use = "if you intended to assert that this is fatal_err, consider `.unwrap_fatal_err()` instead"] 628 | #[inline] 629 | pub fn is_fatal_err(&self) -> bool { 630 | matches!(self, FatalErr(_)) 631 | } 632 | 633 | /// Returns `true` if the result is a [`Success`] value containing the given value. 634 | /// 635 | /// [`Success`]: enum.Result.html#variant.Success 636 | /// 637 | /// # Examples 638 | /// 639 | /// ``` 640 | /// use woah::prelude::*; 641 | /// 642 | /// let x: Result = Success(2); 643 | /// assert_eq!(x.contains(&2), true); 644 | /// 645 | /// let x: Result = Success(3); 646 | /// assert_eq!(x.contains(&2), false); 647 | /// 648 | /// let x: Result = LocalErr("Some error message"); 649 | /// assert_eq!(x.contains(&2), false); 650 | /// ``` 651 | #[must_use] 652 | #[inline] 653 | pub fn contains(&self, x: &U) -> bool 654 | where 655 | U: PartialEq, 656 | { 657 | matches!(self, Success(t) if *x == *t) 658 | } 659 | 660 | /// Returns `true` if the result is a [`LocalErr`] or [`FatalErr`] value containing the given value. 661 | /// 662 | /// [`LocalErr`]: enum.Result.html#variant.LocalErr 663 | /// [`FatalErr`]: enum.Result.html#variant.FatalErr 664 | /// 665 | /// # Examples 666 | /// 667 | /// ``` 668 | /// use woah::prelude::*; 669 | /// use either::Either; 670 | /// 671 | /// let x: Result<&str, u32, &str> = LocalErr(2); 672 | /// let check: Either<_, &&str> = Either::Left(&2); 673 | /// assert_eq!(x.contains_err(check), true); 674 | /// 675 | /// let x: Result<&str, &str, u32> = FatalErr(3); 676 | /// let check: Either<&&str, _> = Either::Right(&2); 677 | /// assert_eq!(x.contains_err(check), false); 678 | /// 679 | /// let x: Result = Success(0); 680 | /// let check: Either<&&str, &&str> = Either::Left(&""); 681 | /// assert_eq!(x.contains_err(check), false); 682 | /// ``` 683 | #[cfg(feature = "either")] 684 | #[must_use] 685 | #[inline] 686 | pub fn contains_err(&self, e: Either<&U, &Y>) -> bool 687 | where 688 | U: PartialEq, 689 | Y: PartialEq, 690 | { 691 | matches!((self, e), (LocalErr(err), Left(e)) if *e == *err) 692 | || matches!((self, e), (FatalErr(err), Right(e)) if *e == *err) 693 | } 694 | 695 | /// Returns `true` if the result is a [`LocalErr`] value containing the given value. 696 | /// 697 | /// [`LocalErr`]: enum.Result.html#variant.LocalErr 698 | /// 699 | /// # Examples 700 | /// 701 | /// ``` 702 | /// use woah::prelude::*; 703 | /// 704 | /// let x: Result<&str, u32, &str> = LocalErr(2); 705 | /// assert_eq!(x.contains_local_err(&2), true); 706 | /// 707 | /// let x: Result<&str, u32, &str> = LocalErr(3); 708 | /// assert_eq!(x.contains_local_err(&2), false); 709 | /// 710 | /// let x: Result<&str, u32, &str> = Success("Some error message"); 711 | /// assert_eq!(x.contains_local_err(&2), false); 712 | /// ``` 713 | #[must_use] 714 | #[inline] 715 | pub fn contains_local_err(&self, e: &E) -> bool 716 | where 717 | E: PartialEq, 718 | { 719 | matches!(self, LocalErr(err) if *e == *err) 720 | } 721 | 722 | /// Returns `true` if the result is a [`FatalErr`] value containing the given value. 723 | /// 724 | /// [`FatalErr`]: enum.Result.html#variant.FatalErr 725 | /// 726 | /// # Examples 727 | /// 728 | /// ``` 729 | /// use woah::prelude::*; 730 | /// 731 | /// let x: Result<&str, &str, u32> = FatalErr(2); 732 | /// assert_eq!(x.contains_fatal_err(&2), true); 733 | /// 734 | /// let x: Result<&str, &str, u32> = FatalErr(3); 735 | /// assert_eq!(x.contains_fatal_err(&2), false); 736 | /// 737 | /// let x: Result<&str, &str, u32> = Success("Some error message"); 738 | /// assert_eq!(x.contains_fatal_err(&2), false); 739 | /// ``` 740 | #[must_use] 741 | #[inline] 742 | pub fn contains_fatal_err(&self, e: &E) -> bool 743 | where 744 | E: PartialEq, 745 | { 746 | matches!(self, FatalErr(err) if *e == *err) 747 | } 748 | 749 | /// Convert a [`Success`] variant to an `Option::Some`, otherwise to a `None`. 750 | /// 751 | /// [`Success`]: enum.Result.html#variant.Success 752 | /// 753 | /// # Example 754 | /// 755 | /// ``` 756 | /// use woah::prelude::*; 757 | /// 758 | /// let x: Result = Success(2); 759 | /// assert_eq!(x.success(), Some(2)); 760 | /// 761 | /// let x: Result<&str, u32, &str> = LocalErr(2); 762 | /// assert_eq!(x.success(), None); 763 | /// 764 | /// let x: Result<&str, &str, u32> = FatalErr(2); 765 | /// assert_eq!(x.success(), None); 766 | /// ``` 767 | #[inline] 768 | pub fn success(self) -> Option { 769 | match self { 770 | Success(t) => Some(t), 771 | _ => None, 772 | } 773 | } 774 | 775 | /// Convert a [`LocalErr`] or [`FatalErr`] variant to an `Option>`, otherwise to a `None`. 776 | /// 777 | /// [`LocalErr`]: enum.Result.html#variant.LocalErr 778 | /// [`FatalErr`]: enum.Result.html#variant.FatalErr 779 | /// 780 | /// # Example 781 | /// 782 | /// ``` 783 | /// use woah::prelude::*; 784 | /// use either::Either::{self, Left, Right}; 785 | /// 786 | /// let x: Result = Success(2); 787 | /// assert_eq!(x.err(), None); 788 | /// 789 | /// let x: Result<&str, u32, &str> = LocalErr(2); 790 | /// assert_eq!(x.err(), Some(Left(2))); 791 | /// 792 | /// let x: Result<&str, &str, u32> = FatalErr(2); 793 | /// assert_eq!(x.err(), Some(Right(2))); 794 | /// ``` 795 | #[cfg(feature = "either")] 796 | #[inline] 797 | pub fn err(self) -> Option> { 798 | match self { 799 | LocalErr(err) => Some(Left(err)), 800 | FatalErr(err) => Some(Right(err)), 801 | _ => None, 802 | } 803 | } 804 | 805 | /// Convert a [`LocalErr`] variant to an `Option::Some`, otherwise to a `None`. 806 | /// 807 | /// [`LocalErr`]: enum.Result.html#variant.LocalErr 808 | /// 809 | /// # Example 810 | /// 811 | /// ``` 812 | /// use woah::prelude::*; 813 | /// 814 | /// let x: Result = Success(2); 815 | /// assert_eq!(x.local_err(), None); 816 | /// 817 | /// let x: Result<&str, u32, &str> = LocalErr(2); 818 | /// assert_eq!(x.local_err(), Some(2)); 819 | /// 820 | /// let x: Result<&str, &str, u32> = FatalErr(2); 821 | /// assert_eq!(x.local_err(), None); 822 | /// ``` 823 | #[inline] 824 | pub fn local_err(self) -> Option { 825 | match self { 826 | LocalErr(err) => Some(err), 827 | _ => None, 828 | } 829 | } 830 | 831 | /// Convert a [`FatalErr`] variant to an `Option::Some`, otherwise to a `None`. 832 | /// 833 | /// [`FatalErr`]: enum.Result.html#variant.FatalErr 834 | /// 835 | /// # Example 836 | /// 837 | /// ``` 838 | /// use woah::prelude::*; 839 | /// 840 | /// let x: Result = Success(2); 841 | /// assert_eq!(x.fatal_err(), None); 842 | /// 843 | /// let x: Result<&str, u32, &str> = LocalErr(2); 844 | /// assert_eq!(x.fatal_err(), None); 845 | /// 846 | /// let x: Result<&str, &str, u32> = FatalErr(2); 847 | /// assert_eq!(x.fatal_err(), Some(2)); 848 | /// ``` 849 | #[inline] 850 | pub fn fatal_err(self) -> Option { 851 | match self { 852 | FatalErr(err) => Some(err), 853 | _ => None, 854 | } 855 | } 856 | 857 | /// Get a reference to the contained value. 858 | /// 859 | /// # Example 860 | /// 861 | /// ``` 862 | /// use woah::prelude::*; 863 | /// 864 | /// let x: Result = Success(0); 865 | /// assert_eq!(x.as_ref(), Success(&0)); 866 | /// 867 | /// let x: Result = LocalErr(0); 868 | /// assert_eq!(x.as_ref(), LocalErr(&0)); 869 | /// 870 | /// let x: Result = FatalErr(0); 871 | /// assert_eq!(x.as_ref(), FatalErr(&0)); 872 | /// ``` 873 | #[inline] 874 | pub fn as_ref(&self) -> Result<&T, &L, &F> { 875 | match self { 876 | Success(t) => Success(t), 877 | LocalErr(err) => LocalErr(err), 878 | FatalErr(err) => FatalErr(err), 879 | } 880 | } 881 | 882 | /// Get a mutable reference to the contained value. 883 | /// 884 | /// # Example 885 | /// 886 | /// ``` 887 | /// use woah::prelude::*; 888 | /// 889 | /// let mut x: Result = Success(0); 890 | /// assert_eq!(x.as_mut(), Success(&mut 0)); 891 | /// 892 | /// let mut x: Result = LocalErr(0); 893 | /// assert_eq!(x.as_mut(), LocalErr(&mut 0)); 894 | /// 895 | /// let mut x: Result = FatalErr(0); 896 | /// assert_eq!(x.as_mut(), FatalErr(&mut 0)); 897 | /// ``` 898 | #[inline] 899 | pub fn as_mut(&mut self) -> Result<&mut T, &mut L, &mut F> { 900 | match self { 901 | Success(t) => Success(t), 902 | LocalErr(err) => LocalErr(err), 903 | FatalErr(err) => FatalErr(err), 904 | } 905 | } 906 | 907 | /// Apply a function to the contained value if it's a [`Success`]. 908 | /// 909 | /// [`Success`]: enum.Result.html#variant.Success 910 | /// 911 | /// # Example 912 | /// 913 | /// ``` 914 | /// use woah::prelude::*; 915 | /// 916 | /// let x: Result = Success(0); 917 | /// assert_eq!(x.map(|s| s + 1), Success(1)); 918 | /// 919 | /// let x: Result = LocalErr(0); 920 | /// assert_eq!(x.map(|s| s + 1), LocalErr(0)); 921 | /// 922 | /// let x: Result = FatalErr(0); 923 | /// assert_eq!(x.map(|s| s + 1), FatalErr(0)); 924 | /// ``` 925 | #[inline] 926 | pub fn map(self, f: U) -> Result 927 | where 928 | U: FnOnce(T) -> S, 929 | { 930 | match self { 931 | Success(t) => Success(f(t)), 932 | LocalErr(e) => LocalErr(e), 933 | FatalErr(e) => FatalErr(e), 934 | } 935 | } 936 | 937 | /// Apply a function to the contained value if it's a [`Success`]. 938 | /// 939 | /// Otherwise return the provided value. 940 | /// 941 | /// [`Success`]: enum.Result.html#variant.Success 942 | /// 943 | /// # Example 944 | /// 945 | /// ``` 946 | /// use woah::prelude::*; 947 | /// 948 | /// let x: Result = Success(0); 949 | /// assert_eq!(x.map_or(5, |s| s + 1), 1); 950 | /// 951 | /// let x: Result = LocalErr(0); 952 | /// assert_eq!(x.map_or(5, |s| s + 1), 5); 953 | /// 954 | /// let x: Result = FatalErr(0); 955 | /// assert_eq!(x.map_or(5, |s| s + 1), 5); 956 | /// ``` 957 | #[inline] 958 | pub fn map_or(self, default: U, f: G) -> U 959 | where 960 | G: FnOnce(T) -> U, 961 | { 962 | match self { 963 | Success(t) => f(t), 964 | _ => default, 965 | } 966 | } 967 | 968 | /// Apply a function to the contained value if it's a [`Success`]. 969 | /// 970 | /// Otherwise run one of the provided default functions. 971 | /// 972 | /// [`Success`]: enum.Result.html#variant.Success 973 | /// 974 | /// # Example 975 | /// 976 | /// ``` 977 | /// use woah::prelude::*; 978 | /// 979 | /// let x: Result = Success(0); 980 | /// assert_eq!(x.map_or_else(|l| l + 3, |f| f + 2, |s| s + 1), 1); 981 | /// 982 | /// let x: Result = LocalErr(0); 983 | /// assert_eq!(x.map_or_else(|l| l + 3, |f| f + 2, |s| s + 1), 3); 984 | /// 985 | /// let x: Result = FatalErr(0); 986 | /// assert_eq!(x.map_or_else(|l| l + 3, |f| f + 2, |s| s + 1), 2); 987 | /// ``` 988 | #[inline] 989 | pub fn map_or_else(self, default_local: LD, default_fatal: FD, f: G) -> U 990 | where 991 | LD: FnOnce(L) -> U, 992 | FD: FnOnce(F) -> U, 993 | G: FnOnce(T) -> U, 994 | { 995 | match self { 996 | Success(t) => f(t), 997 | LocalErr(err) => default_local(err), 998 | FatalErr(err) => default_fatal(err), 999 | } 1000 | } 1001 | 1002 | /// Apply a function to the contained value if it's a [`LocalErr`] or [`FatalErr`]. 1003 | /// 1004 | /// [`LocalErr`]: enum.Result.html#variant.LocalErr 1005 | /// [`FatalErr`]: enum.Result.html#variant.FatalErr 1006 | /// 1007 | /// # Example 1008 | /// 1009 | /// ``` 1010 | /// use woah::prelude::*; 1011 | /// use either::Either::{self, Left, Right}; 1012 | /// 1013 | /// fn modify_error(err: Either) -> Either { 1014 | /// match err { 1015 | /// Left(l) => Left(l + 1), 1016 | /// Right(f) => Right(f + 1), 1017 | /// } 1018 | /// } 1019 | /// 1020 | /// let x: Result = Success(0); 1021 | /// assert_eq!(x.map_err(modify_error), Success(0)); 1022 | /// 1023 | /// let x: Result = LocalErr(0); 1024 | /// assert_eq!(x.map_err(modify_error), LocalErr(1)); 1025 | /// 1026 | /// let x: Result = FatalErr(0); 1027 | /// assert_eq!(x.map_err(modify_error), FatalErr(1)); 1028 | /// ``` 1029 | #[cfg(feature = "either")] 1030 | #[inline] 1031 | pub fn map_err(self, f: U) -> Result 1032 | where 1033 | U: FnOnce(Either) -> Either, 1034 | { 1035 | match self { 1036 | Success(t) => Success(t), 1037 | LocalErr(err) => match f(Left(err)) { 1038 | Left(err) => LocalErr(err), 1039 | Right(err) => FatalErr(err), 1040 | }, 1041 | FatalErr(err) => match f(Right(err)) { 1042 | Left(err) => LocalErr(err), 1043 | Right(err) => FatalErr(err), 1044 | }, 1045 | } 1046 | } 1047 | 1048 | /// Apply a function to the contained value if it's a [`LocalErr`]. 1049 | /// 1050 | /// [`LocalErr`]: enum.Result.html#variant.LocalErr 1051 | /// 1052 | /// # Example 1053 | /// 1054 | /// ``` 1055 | /// use woah::prelude::*; 1056 | /// 1057 | /// let x: Result = Success(0); 1058 | /// assert_eq!(x.map_local_err(|l| l + 1), Success(0)); 1059 | /// 1060 | /// let x: Result = LocalErr(0); 1061 | /// assert_eq!(x.map_local_err(|l| l + 1), LocalErr(1)); 1062 | /// 1063 | /// let x: Result = FatalErr(0); 1064 | /// assert_eq!(x.map_local_err(|l| l + 1), FatalErr(0)); 1065 | /// ``` 1066 | #[inline] 1067 | pub fn map_local_err(self, f: U) -> Result 1068 | where 1069 | U: FnOnce(L) -> S, 1070 | { 1071 | match self { 1072 | Success(t) => Success(t), 1073 | LocalErr(e) => LocalErr(f(e)), 1074 | FatalErr(e) => FatalErr(e), 1075 | } 1076 | } 1077 | 1078 | /// Apply a function to the contained value if it's a [`FatalErr`]. 1079 | /// 1080 | /// [`FatalErr`]: enum.Result.html#variant.FatalErr 1081 | /// 1082 | /// # Example 1083 | /// 1084 | /// ``` 1085 | /// use woah::prelude::*; 1086 | /// 1087 | /// let x: Result = Success(0); 1088 | /// assert_eq!(x.map_fatal_err(|f| f + 1), Success(0)); 1089 | /// 1090 | /// let x: Result = LocalErr(0); 1091 | /// assert_eq!(x.map_fatal_err(|f| f + 1), LocalErr(0)); 1092 | /// 1093 | /// let x: Result = FatalErr(0); 1094 | /// assert_eq!(x.map_fatal_err(|f| f + 1), FatalErr(1)); 1095 | /// ``` 1096 | #[inline] 1097 | pub fn map_fatal_err(self, f: U) -> Result 1098 | where 1099 | U: FnOnce(F) -> S, 1100 | { 1101 | match self { 1102 | Success(t) => Success(t), 1103 | LocalErr(e) => LocalErr(e), 1104 | FatalErr(e) => FatalErr(f(e)), 1105 | } 1106 | } 1107 | 1108 | /// Get an iterator over the inner value in the `Result`, if it's a [`Success`]. 1109 | /// 1110 | /// [`Success`]: enum.Result.html#variant.Success 1111 | /// 1112 | /// # Example 1113 | /// 1114 | /// ``` 1115 | /// use woah::prelude::*; 1116 | /// 1117 | /// let r: Result = Success(0); 1118 | /// 1119 | /// assert_eq!(r.iter().next(), Some(&0)); 1120 | /// ``` 1121 | #[inline] 1122 | pub fn iter(&self) -> Iter { 1123 | let inner = match self { 1124 | Success(t) => Some(t), 1125 | _ => None, 1126 | }; 1127 | 1128 | Iter { inner } 1129 | } 1130 | 1131 | /// Get a mutable iterator over the inner value in the `Result`, if it's a [`Success`]. 1132 | /// 1133 | /// [`Success`]: enum.Result.html#variant.Success 1134 | /// 1135 | /// # Example 1136 | /// 1137 | /// ``` 1138 | /// use woah::prelude::*; 1139 | /// 1140 | /// let mut r: Result = Success(0); 1141 | /// 1142 | /// { 1143 | /// let next = r.iter_mut().next(); 1144 | /// 1145 | /// assert!(next.is_some()); 1146 | /// 1147 | /// *next.unwrap() = 5; 1148 | /// } 1149 | /// 1150 | /// assert_eq!(r, Success(5)); 1151 | /// ``` 1152 | #[inline] 1153 | pub fn iter_mut(&mut self) -> IterMut { 1154 | let inner = match self { 1155 | Success(t) => Some(t), 1156 | _ => None, 1157 | }; 1158 | 1159 | IterMut { inner } 1160 | } 1161 | 1162 | /// If it's a [`Success`], replace it with `res`. 1163 | /// 1164 | /// [`Success`]: enum.Result.html#variant.Success 1165 | /// 1166 | /// # Example 1167 | /// 1168 | /// ``` 1169 | /// use woah::prelude::*; 1170 | /// 1171 | /// let r1: Result = Success(0); 1172 | /// let r2: Result = r1.and(LocalErr("")); 1173 | /// assert_eq!(r2, LocalErr("")); 1174 | /// ``` 1175 | #[inline] 1176 | pub fn and(self, res: Result) -> Result { 1177 | match self { 1178 | Success(_) => res, 1179 | LocalErr(err) => LocalErr(err), 1180 | FatalErr(err) => FatalErr(err), 1181 | } 1182 | } 1183 | 1184 | /// If it's a [`Success`], replace it with the result of `op`. 1185 | /// 1186 | /// [`Success`]: enum.Result.html#variant.Success 1187 | /// 1188 | /// # Example 1189 | /// 1190 | /// ``` 1191 | /// use woah::prelude::*; 1192 | /// 1193 | /// let r1: Result = Success(0); 1194 | /// let r2: Result = r1.and_then(|c| { 1195 | /// if c == 0 { 1196 | /// LocalErr("local") 1197 | /// } else { 1198 | /// FatalErr("fatal") 1199 | /// } 1200 | /// }); 1201 | /// 1202 | /// assert_eq!(r2, LocalErr("local")); 1203 | /// ``` 1204 | #[inline] 1205 | pub fn and_then(self, op: G) -> Result 1206 | where 1207 | G: FnOnce(T) -> Result, 1208 | { 1209 | match self { 1210 | Success(t) => op(t), 1211 | LocalErr(err) => LocalErr(err), 1212 | FatalErr(err) => FatalErr(err), 1213 | } 1214 | } 1215 | 1216 | /// If it's a [`LocalErr`] or [`FatalErr`], replace them with the appropriate value. 1217 | /// 1218 | /// [`LocalErr`]: enum.Result.html#variant.LocalErr 1219 | /// [`FatalErr`]: enum.Result.html#variant.FatalErr 1220 | /// 1221 | /// # Example 1222 | /// 1223 | /// ``` 1224 | /// use woah::prelude::*; 1225 | /// 1226 | /// let l: Result = LocalErr(1); 1227 | /// let f: Result = FatalErr(2); 1228 | /// 1229 | /// let r: Result = Success(0); 1230 | /// assert_eq!(r.or(l, f), Success(0)); 1231 | /// 1232 | /// let r: Result = LocalErr(0); 1233 | /// assert_eq!(r.or(l, f), LocalErr(1)); 1234 | /// 1235 | /// let r: Result = FatalErr(0); 1236 | /// assert_eq!(r.or(l, f), FatalErr(2)); 1237 | /// ``` 1238 | #[inline] 1239 | pub fn or( 1240 | self, 1241 | res_local: Result, 1242 | res_fatal: Result, 1243 | ) -> Result { 1244 | match self { 1245 | Success(t) => Success(t), 1246 | LocalErr(_) => res_local, 1247 | FatalErr(_) => res_fatal, 1248 | } 1249 | } 1250 | 1251 | /// If it's a [`LocalErr`], replace them with the given value. 1252 | /// 1253 | /// [`LocalErr`]: enum.Result.html#variant.LocalErr 1254 | /// 1255 | /// # Example 1256 | /// 1257 | /// ``` 1258 | /// use woah::prelude::*; 1259 | /// 1260 | /// let l: Result = LocalErr(1); 1261 | /// 1262 | /// let r: Result = Success(0); 1263 | /// assert_eq!(r.or_local(l), Success(0)); 1264 | /// 1265 | /// let r: Result = LocalErr(0); 1266 | /// assert_eq!(r.or_local(l), LocalErr(1)); 1267 | /// 1268 | /// let r: Result = FatalErr(0); 1269 | /// assert_eq!(r.or_local(l), FatalErr(0)); 1270 | /// ``` 1271 | #[inline] 1272 | pub fn or_local(self, res: Result) -> Result { 1273 | match self { 1274 | Success(t) => Success(t), 1275 | LocalErr(_) => res, 1276 | FatalErr(err) => FatalErr(err), 1277 | } 1278 | } 1279 | 1280 | /// If it's a [`FatalErr`], replace them with the given value. 1281 | /// 1282 | /// [`FatalErr`]: enum.Result.html#variant.FatalErr 1283 | /// 1284 | /// # Example 1285 | /// 1286 | /// ``` 1287 | /// use woah::prelude::*; 1288 | /// 1289 | /// let f: Result = FatalErr(2); 1290 | /// 1291 | /// let r: Result = Success(0); 1292 | /// assert_eq!(r.or_fatal(f), Success(0)); 1293 | /// 1294 | /// let r: Result = LocalErr(0); 1295 | /// assert_eq!(r.or_fatal(f), LocalErr(0)); 1296 | /// 1297 | /// let r: Result = FatalErr(0); 1298 | /// assert_eq!(r.or_fatal(f), FatalErr(2)); 1299 | /// ``` 1300 | #[inline] 1301 | pub fn or_fatal(self, res: Result) -> Result { 1302 | match self { 1303 | Success(t) => Success(t), 1304 | LocalErr(err) => LocalErr(err), 1305 | FatalErr(_) => res, 1306 | } 1307 | } 1308 | 1309 | /// If it's a [`LocalErr`] or [`FatalErr`], replace them with the appropriate function result. 1310 | /// 1311 | /// [`LocalErr`]: enum.Result.html#variant.LocalErr 1312 | /// [`FatalErr`]: enum.Result.html#variant.FatalErr 1313 | /// 1314 | /// # Example 1315 | /// 1316 | /// ``` 1317 | /// use woah::prelude::*; 1318 | /// 1319 | /// let l = |l| LocalErr(l + 1); 1320 | /// let f = |f| FatalErr(f + 2); 1321 | /// 1322 | /// let r: Result = Success(0); 1323 | /// assert_eq!(r.or_else(l, f), Success(0)); 1324 | /// 1325 | /// let r: Result = LocalErr(0); 1326 | /// assert_eq!(r.or_else(l, f), LocalErr(1)); 1327 | /// 1328 | /// let r: Result = FatalErr(0); 1329 | /// assert_eq!(r.or_else(l, f), FatalErr(2)); 1330 | /// ``` 1331 | #[inline] 1332 | pub fn or_else(self, op_local: O, op_fatal: P) -> Result 1333 | where 1334 | O: FnOnce(L) -> Result, 1335 | P: FnOnce(F) -> Result, 1336 | { 1337 | match self { 1338 | Success(t) => Success(t), 1339 | LocalErr(err) => op_local(err), 1340 | FatalErr(err) => op_fatal(err), 1341 | } 1342 | } 1343 | 1344 | /// If it's a [`LocalErr`], replace it with the appropriate function result. 1345 | /// 1346 | /// [`LocalErr`]: enum.Result.html#variant.LocalErr 1347 | /// 1348 | /// # Example 1349 | /// 1350 | /// ``` 1351 | /// use woah::prelude::*; 1352 | /// 1353 | /// let l = |l| LocalErr(l + 1); 1354 | /// 1355 | /// let r: Result = Success(0); 1356 | /// assert_eq!(r.or_else_local(l), Success(0)); 1357 | /// 1358 | /// let r: Result = LocalErr(0); 1359 | /// assert_eq!(r.or_else_local(l), LocalErr(1)); 1360 | /// 1361 | /// let r: Result = FatalErr(0); 1362 | /// assert_eq!(r.or_else_local(l), FatalErr(0)); 1363 | /// ``` 1364 | #[inline] 1365 | pub fn or_else_local(self, op: O) -> Result 1366 | where 1367 | O: FnOnce(L) -> Result, 1368 | { 1369 | match self { 1370 | Success(t) => Success(t), 1371 | LocalErr(err) => op(err), 1372 | FatalErr(err) => FatalErr(err), 1373 | } 1374 | } 1375 | 1376 | /// If it's a [`FatalErr`], replace it with the appropriate function result. 1377 | /// 1378 | /// [`FatalErr`]: enum.Result.html#variant.FatalErr 1379 | /// 1380 | /// # Example 1381 | /// 1382 | /// ``` 1383 | /// use woah::prelude::*; 1384 | /// 1385 | /// let f = |f| FatalErr(f + 2); 1386 | /// 1387 | /// let r: Result = Success(0); 1388 | /// assert_eq!(r.or_else_fatal(f), Success(0)); 1389 | /// 1390 | /// let r: Result = LocalErr(0); 1391 | /// assert_eq!(r.or_else_fatal(f), LocalErr(0)); 1392 | /// 1393 | /// let r: Result = FatalErr(0); 1394 | /// assert_eq!(r.or_else_fatal(f), FatalErr(2)); 1395 | /// ``` 1396 | #[inline] 1397 | pub fn or_else_fatal(self, op: O) -> Result 1398 | where 1399 | O: FnOnce(F) -> Result, 1400 | { 1401 | match self { 1402 | Success(t) => Success(t), 1403 | LocalErr(err) => LocalErr(err), 1404 | FatalErr(err) => op(err), 1405 | } 1406 | } 1407 | 1408 | /// Return inner value if it's a [`Success`], or `alt` otherwise. 1409 | /// 1410 | /// [`Success`]: enum.Result.html#variant.Success 1411 | /// 1412 | /// # Example 1413 | /// 1414 | /// ``` 1415 | /// use woah::prelude::*; 1416 | /// 1417 | /// let r: Result = Success(0); 1418 | /// assert_eq!(r.unwrap_or(5), 0); 1419 | /// 1420 | /// let r: Result = LocalErr(0); 1421 | /// assert_eq!(r.unwrap_or(5), 5); 1422 | /// 1423 | /// let r: Result = FatalErr(0); 1424 | /// assert_eq!(r.unwrap_or(5), 5); 1425 | /// ``` 1426 | #[inline] 1427 | pub fn unwrap_or(self, alt: T) -> T { 1428 | match self { 1429 | Success(t) => t, 1430 | _ => alt, 1431 | } 1432 | } 1433 | 1434 | /// Return inner value if it's a [`Success`], or the appropriate function otherwise. 1435 | /// 1436 | /// [`Success`]: enum.Result.html#variant.Success 1437 | /// 1438 | /// # Example 1439 | /// 1440 | /// ``` 1441 | /// use woah::prelude::*; 1442 | /// 1443 | /// let l = |_| 5; 1444 | /// let f = |_| 10; 1445 | /// 1446 | /// let r: Result = Success(0); 1447 | /// assert_eq!(r.unwrap_or_else(l, f), 0); 1448 | /// 1449 | /// let r: Result = LocalErr(0); 1450 | /// assert_eq!(r.unwrap_or_else(l, f), 5); 1451 | /// 1452 | /// let r: Result = FatalErr(0); 1453 | /// assert_eq!(r.unwrap_or_else(l, f), 10); 1454 | /// ``` 1455 | #[inline] 1456 | pub fn unwrap_or_else(self, local_op: M, fatal_op: G) -> T 1457 | where 1458 | M: FnOnce(L) -> T, 1459 | G: FnOnce(F) -> T, 1460 | { 1461 | match self { 1462 | Success(t) => t, 1463 | LocalErr(err) => local_op(err), 1464 | FatalErr(err) => fatal_op(err), 1465 | } 1466 | } 1467 | } 1468 | 1469 | impl<'a, T, L, F> Result<&'a T, L, F> 1470 | where 1471 | T: Copy, 1472 | { 1473 | /// Copy the value if it's a [`Success`]. 1474 | /// 1475 | /// [`Success`]: enum.Result.html#variant.Success 1476 | /// 1477 | /// # Example 1478 | /// 1479 | /// ``` 1480 | /// use woah::prelude::*; 1481 | /// 1482 | /// let r: Result<&u32, (), ()> = Success(&0); 1483 | /// assert_eq!(r.copied(), Success(0)); 1484 | /// ``` 1485 | #[inline] 1486 | pub fn copied(self) -> Result { 1487 | match self { 1488 | Success(t) => Success(*t), 1489 | LocalErr(err) => LocalErr(err), 1490 | FatalErr(err) => FatalErr(err), 1491 | } 1492 | } 1493 | } 1494 | 1495 | impl<'a, T, L, F> Result<&'a mut T, L, F> 1496 | where 1497 | T: Copy, 1498 | { 1499 | /// Copy the value if it's a [`Success`]. 1500 | /// 1501 | /// [`Success`]: enum.Result.html#variant.Success 1502 | /// 1503 | /// # Example 1504 | /// 1505 | /// ``` 1506 | /// use woah::prelude::*; 1507 | /// 1508 | /// let r: Result<&u32, (), ()> = Success(&0); 1509 | /// assert_eq!(r.copied(), Success(0)); 1510 | /// ``` 1511 | #[inline] 1512 | pub fn copied(self) -> Result { 1513 | match self { 1514 | Success(t) => Success(*t), 1515 | LocalErr(err) => LocalErr(err), 1516 | FatalErr(err) => FatalErr(err), 1517 | } 1518 | } 1519 | } 1520 | 1521 | impl<'a, T, L, F> Result<&'a T, L, F> 1522 | where 1523 | T: Clone, 1524 | { 1525 | /// Clone the value if it's a [`Success`]. 1526 | /// 1527 | /// [`Success`]: enum.Result.html#variant.Success 1528 | /// 1529 | /// # Example 1530 | /// 1531 | /// ``` 1532 | /// use woah::prelude::*; 1533 | /// 1534 | /// let r: Result<&u32, (), ()> = Success(&0); 1535 | /// assert_eq!(r.cloned(), Success(0)); 1536 | /// ``` 1537 | #[inline] 1538 | pub fn cloned(self) -> Result { 1539 | match self { 1540 | Success(t) => Success(t.clone()), 1541 | LocalErr(err) => LocalErr(err), 1542 | FatalErr(err) => FatalErr(err), 1543 | } 1544 | } 1545 | } 1546 | 1547 | impl<'a, T, L, F> Result<&'a mut T, L, F> 1548 | where 1549 | T: Clone, 1550 | { 1551 | /// Clone the value if it's a [`Success`]. 1552 | /// 1553 | /// [`Success`]: enum.Result.html#variant.Success 1554 | /// 1555 | /// # Example 1556 | /// 1557 | /// ``` 1558 | /// use woah::prelude::*; 1559 | /// 1560 | /// let r: Result<&u32, (), ()> = Success(&0); 1561 | /// assert_eq!(r.cloned(), Success(0)); 1562 | /// ``` 1563 | #[inline] 1564 | pub fn cloned(self) -> Result { 1565 | match self { 1566 | Success(t) => Success(t.clone()), 1567 | LocalErr(err) => LocalErr(err), 1568 | FatalErr(err) => FatalErr(err), 1569 | } 1570 | } 1571 | } 1572 | 1573 | impl Result 1574 | where 1575 | L: Debug, 1576 | F: Debug, 1577 | { 1578 | /// Get the value if it's a [`Success`], panic otherwise. 1579 | /// 1580 | /// [`Success`]: enum.Result.html#variant.Success 1581 | /// 1582 | /// # Example 1583 | /// 1584 | /// ``` 1585 | /// use woah::prelude::*; 1586 | /// 1587 | /// let r: Result = Success(0); 1588 | /// assert_eq!(r.unwrap(), 0); 1589 | /// ``` 1590 | #[inline] 1591 | pub fn unwrap(self) -> T { 1592 | match self { 1593 | Success(t) => t, 1594 | LocalErr(err) => panic!("{:?}", err), 1595 | FatalErr(err) => panic!("{:?}", err), 1596 | } 1597 | } 1598 | 1599 | /// Get the value if it's a [`Success`], panic with a `msg` otherwise. 1600 | /// 1601 | /// [`Success`]: enum.Result.html#variant.Success 1602 | /// 1603 | /// # Example 1604 | /// 1605 | /// ``` 1606 | /// use woah::prelude::*; 1607 | /// 1608 | /// let r: Result = Success(0); 1609 | /// assert_eq!(r.expect("should be success"), 0); 1610 | /// ``` 1611 | #[inline] 1612 | pub fn expect(self, msg: &str) -> T { 1613 | match self { 1614 | Success(t) => t, 1615 | LocalErr(_) => panic!("{}", msg), 1616 | FatalErr(_) => panic!("{}", msg), 1617 | } 1618 | } 1619 | } 1620 | 1621 | #[cfg(feature = "either")] 1622 | impl Result 1623 | where 1624 | T: Debug, 1625 | L: Debug, 1626 | F: Debug, 1627 | { 1628 | #[inline] 1629 | pub fn unwrap_err(self) -> Either { 1630 | match self { 1631 | Success(t) => panic!("{:?}", t), 1632 | LocalErr(err) => Left(err), 1633 | FatalErr(err) => Right(err), 1634 | } 1635 | } 1636 | 1637 | #[inline] 1638 | pub fn expect_err(self, msg: &str) -> Either { 1639 | match self { 1640 | Success(_) => panic!("{}", msg), 1641 | LocalErr(err) => Left(err), 1642 | FatalErr(err) => Right(err), 1643 | } 1644 | } 1645 | } 1646 | 1647 | impl Result 1648 | where 1649 | T: Debug, 1650 | F: Debug, 1651 | { 1652 | #[inline] 1653 | pub fn unwrap_local_err(self) -> L { 1654 | match self { 1655 | Success(t) => panic!("{:?}", t), 1656 | LocalErr(err) => err, 1657 | FatalErr(err) => panic!("{:?}", err), 1658 | } 1659 | } 1660 | 1661 | #[inline] 1662 | pub fn expect_local_err(self, msg: &str) -> L { 1663 | match self { 1664 | Success(_) => panic!("{}", msg), 1665 | LocalErr(err) => err, 1666 | FatalErr(_) => panic!("{}", msg), 1667 | } 1668 | } 1669 | } 1670 | 1671 | impl Result 1672 | where 1673 | T: Debug, 1674 | L: Debug, 1675 | { 1676 | #[inline] 1677 | pub fn unwrap_fatal_err(self) -> F { 1678 | match self { 1679 | Success(t) => panic!("{:?}", t), 1680 | LocalErr(err) => panic!("{:?}", err), 1681 | FatalErr(err) => err, 1682 | } 1683 | } 1684 | 1685 | #[inline] 1686 | pub fn expect_fatal_err(self, msg: &str) -> F { 1687 | match self { 1688 | Success(_) => panic!("{}", msg), 1689 | LocalErr(_) => panic!("{}", msg), 1690 | FatalErr(err) => err, 1691 | } 1692 | } 1693 | } 1694 | 1695 | impl Result 1696 | where 1697 | T: Default, 1698 | { 1699 | #[inline] 1700 | pub fn unwrap_or_default(self) -> T { 1701 | match self { 1702 | Success(t) => t, 1703 | _ => T::default(), 1704 | } 1705 | } 1706 | 1707 | #[inline] 1708 | pub fn into_result_default(self) -> StdResult { 1709 | match self { 1710 | Success(t) => Ok(t), 1711 | LocalErr(_) => Ok(T::default()), 1712 | FatalErr(err) => Err(err), 1713 | } 1714 | } 1715 | } 1716 | 1717 | #[cfg(feature = "nightly")] 1718 | impl Result 1719 | where 1720 | L: Into, 1721 | F: Into, 1722 | { 1723 | #[inline] 1724 | pub fn into_success(self) -> T { 1725 | match self { 1726 | Success(t) => t, 1727 | LocalErr(err) => err.into(), 1728 | FatalErr(err) => err.into(), 1729 | } 1730 | } 1731 | } 1732 | 1733 | impl Result 1734 | where 1735 | T: Deref, 1736 | { 1737 | #[inline] 1738 | pub fn as_deref(&self) -> Result<&::Target, &L, &F> { 1739 | match self { 1740 | Success(t) => Success(t.deref()), 1741 | LocalErr(err) => LocalErr(err), 1742 | FatalErr(err) => FatalErr(err), 1743 | } 1744 | } 1745 | } 1746 | 1747 | impl Result 1748 | where 1749 | L: Deref, 1750 | F: Deref, 1751 | { 1752 | #[inline] 1753 | pub fn as_deref_err(&self) -> Result<&T, &::Target, &::Target> { 1754 | match self { 1755 | Success(t) => Success(t), 1756 | LocalErr(err) => LocalErr(err.deref()), 1757 | FatalErr(err) => FatalErr(err.deref()), 1758 | } 1759 | } 1760 | } 1761 | 1762 | impl Result 1763 | where 1764 | L: Deref, 1765 | { 1766 | #[inline] 1767 | pub fn as_deref_local_err(&self) -> Result<&T, &::Target, &F> { 1768 | match self { 1769 | Success(t) => Success(t), 1770 | LocalErr(err) => LocalErr(err.deref()), 1771 | FatalErr(err) => FatalErr(err), 1772 | } 1773 | } 1774 | } 1775 | 1776 | impl Result 1777 | where 1778 | F: Deref, 1779 | { 1780 | #[inline] 1781 | pub fn as_deref_fatal_err(&self) -> Result<&T, &L, &::Target> { 1782 | match self { 1783 | Success(t) => Success(t), 1784 | LocalErr(err) => LocalErr(err), 1785 | FatalErr(err) => FatalErr(err.deref()), 1786 | } 1787 | } 1788 | } 1789 | 1790 | impl Result 1791 | where 1792 | T: DerefMut, 1793 | { 1794 | #[inline] 1795 | pub fn as_deref_mut(&mut self) -> Result<&mut ::Target, &mut L, &mut F> { 1796 | match self { 1797 | Success(t) => Success(t.deref_mut()), 1798 | LocalErr(err) => LocalErr(err), 1799 | FatalErr(err) => FatalErr(err), 1800 | } 1801 | } 1802 | } 1803 | 1804 | impl Result 1805 | where 1806 | L: DerefMut, 1807 | F: DerefMut, 1808 | { 1809 | #[inline] 1810 | pub fn as_deref_mut_err( 1811 | &mut self, 1812 | ) -> Result<&mut T, &mut ::Target, &mut ::Target> { 1813 | match self { 1814 | Success(t) => Success(t), 1815 | LocalErr(err) => LocalErr(err.deref_mut()), 1816 | FatalErr(err) => FatalErr(err.deref_mut()), 1817 | } 1818 | } 1819 | } 1820 | 1821 | impl Result 1822 | where 1823 | L: DerefMut, 1824 | { 1825 | #[inline] 1826 | pub fn as_deref_mut_local_err(&mut self) -> Result<&mut T, &mut ::Target, &mut F> { 1827 | match self { 1828 | Success(t) => Success(t), 1829 | LocalErr(err) => LocalErr(err.deref_mut()), 1830 | FatalErr(err) => FatalErr(err), 1831 | } 1832 | } 1833 | } 1834 | 1835 | impl Result 1836 | where 1837 | F: DerefMut, 1838 | { 1839 | #[inline] 1840 | pub fn as_deref_mut_fatal_err(&mut self) -> Result<&mut T, &mut L, &mut ::Target> { 1841 | match self { 1842 | Success(t) => Success(t), 1843 | LocalErr(err) => LocalErr(err), 1844 | FatalErr(err) => FatalErr(err.deref_mut()), 1845 | } 1846 | } 1847 | } 1848 | 1849 | impl Result, L, F> { 1850 | #[inline] 1851 | pub fn transpose(self) -> Option> { 1852 | match self { 1853 | Success(Some(t)) => Some(Success(t)), 1854 | Success(None) => None, 1855 | LocalErr(err) => Some(LocalErr(err)), 1856 | FatalErr(err) => Some(FatalErr(err)), 1857 | } 1858 | } 1859 | } 1860 | 1861 | impl Clone for Result 1862 | where 1863 | T: Clone, 1864 | L: Clone, 1865 | F: Clone, 1866 | { 1867 | #[inline] 1868 | fn clone(&self) -> Result { 1869 | match self { 1870 | Success(t) => Success(t.clone()), 1871 | LocalErr(err) => LocalErr(err.clone()), 1872 | FatalErr(err) => FatalErr(err.clone()), 1873 | } 1874 | } 1875 | 1876 | #[inline] 1877 | fn clone_from(&mut self, source: &Result) { 1878 | match (self, source) { 1879 | (Success(to), Success(from)) => to.clone_from(from), 1880 | (LocalErr(to), LocalErr(from)) => to.clone_from(from), 1881 | (FatalErr(to), FatalErr(from)) => to.clone_from(from), 1882 | (to, from) => *to = from.clone(), 1883 | } 1884 | } 1885 | } 1886 | 1887 | #[cfg(feature = "nightly")] 1888 | impl FromIterator> for Result 1889 | where 1890 | V: FromIterator, 1891 | { 1892 | #[inline] 1893 | fn from_iter(iter: I) -> Result 1894 | where 1895 | I: IntoIterator>, 1896 | { 1897 | process_results(iter.into_iter(), |i| i.collect()) 1898 | } 1899 | } 1900 | 1901 | impl<'a, T, L, F> IntoIterator for &'a mut Result { 1902 | type Item = &'a mut T; 1903 | type IntoIter = IterMut<'a, T>; 1904 | 1905 | #[inline] 1906 | fn into_iter(self) -> IterMut<'a, T> { 1907 | self.iter_mut() 1908 | } 1909 | } 1910 | 1911 | impl<'a, T, L, F> IntoIterator for &'a Result { 1912 | type Item = &'a T; 1913 | type IntoIter = Iter<'a, T>; 1914 | 1915 | #[inline] 1916 | fn into_iter(self) -> Iter<'a, T> { 1917 | self.iter() 1918 | } 1919 | } 1920 | 1921 | impl IntoIterator for Result { 1922 | type Item = T; 1923 | type IntoIter = IntoIter; 1924 | 1925 | #[inline] 1926 | fn into_iter(self) -> IntoIter { 1927 | IntoIter { 1928 | inner: self.success(), 1929 | } 1930 | } 1931 | } 1932 | 1933 | #[cfg(feature = "nightly")] 1934 | impl Product> for Result 1935 | where 1936 | T: Product, 1937 | { 1938 | #[inline] 1939 | fn product(iter: I) -> Result 1940 | where 1941 | I: Iterator>, 1942 | { 1943 | process_results(iter, |i| i.product()) 1944 | } 1945 | } 1946 | 1947 | #[cfg(feature = "nightly")] 1948 | impl Sum> for Result 1949 | where 1950 | T: Sum, 1951 | { 1952 | #[inline] 1953 | fn sum(iter: I) -> Result 1954 | where 1955 | I: Iterator>, 1956 | { 1957 | process_results(iter, |i| i.sum()) 1958 | } 1959 | } 1960 | 1961 | #[cfg(feature = "std")] 1962 | impl Termination for Result<(), L, F> 1963 | where 1964 | L: Debug, 1965 | F: Debug, 1966 | { 1967 | #[inline] 1968 | fn report(self) -> ExitCode { 1969 | match self { 1970 | Success(()) => ().report(), 1971 | LocalErr(err) => { 1972 | eprintln!("Error: {:?}", err); 1973 | ExitCode::FAILURE.report() 1974 | } 1975 | FatalErr(err) => { 1976 | eprintln!("Error: {:?}", err); 1977 | ExitCode::FAILURE.report() 1978 | } 1979 | } 1980 | } 1981 | } 1982 | 1983 | #[cfg(all(feature = "nightly", feature = "std"))] 1984 | impl Termination for Result 1985 | where 1986 | L: Debug, 1987 | F: Debug, 1988 | { 1989 | #[inline] 1990 | fn report(self) -> ExitCode { 1991 | match self { 1992 | LocalErr(err) => { 1993 | eprintln!("Error: {:?}", err); 1994 | ExitCode::FAILURE.report() 1995 | } 1996 | FatalErr(err) => { 1997 | eprintln!("Error: {:?}", err); 1998 | ExitCode::FAILURE.report() 1999 | } 2000 | Success(t) => t, 2001 | } 2002 | } 2003 | } 2004 | 2005 | /// An iterator over the value in an `Success` variant of a `woah::Result`. 2006 | #[derive(Debug)] 2007 | pub struct IntoIter { 2008 | inner: Option, 2009 | } 2010 | 2011 | impl Iterator for IntoIter { 2012 | type Item = T; 2013 | 2014 | #[inline] 2015 | fn next(&mut self) -> Option { 2016 | self.inner.take() 2017 | } 2018 | } 2019 | 2020 | /// An iterator over a reference to the `Success` variant of a `woah::Result`. 2021 | #[derive(Debug)] 2022 | pub struct Iter<'a, T: 'a> { 2023 | inner: Option<&'a T>, 2024 | } 2025 | 2026 | impl<'a, T> Iterator for Iter<'a, T> { 2027 | type Item = &'a T; 2028 | 2029 | #[inline] 2030 | fn next(&mut self) -> Option<&'a T> { 2031 | self.inner.take() 2032 | } 2033 | 2034 | #[inline] 2035 | fn size_hint(&self) -> (usize, Option) { 2036 | let n = if self.inner.is_some() { 1 } else { 0 }; 2037 | (n, Some(n)) 2038 | } 2039 | } 2040 | 2041 | impl<'a, T> DoubleEndedIterator for Iter<'a, T> { 2042 | #[inline] 2043 | fn next_back(&mut self) -> Option<&'a T> { 2044 | self.inner.take() 2045 | } 2046 | } 2047 | 2048 | impl<'a, T> FusedIterator for Iter<'a, T> {} 2049 | 2050 | #[cfg(feature = "nightly")] 2051 | unsafe impl<'a, T> TrustedLen for Iter<'a, T> {} 2052 | 2053 | /// An iterator over a mutable reference to the `Success` variant of a `woah::Result`. 2054 | #[derive(Debug)] 2055 | pub struct IterMut<'a, T: 'a> { 2056 | inner: Option<&'a mut T>, 2057 | } 2058 | 2059 | impl<'a, T> Iterator for IterMut<'a, T> { 2060 | type Item = &'a mut T; 2061 | 2062 | #[inline] 2063 | fn next(&mut self) -> Option<&'a mut T> { 2064 | self.inner.take() 2065 | } 2066 | 2067 | #[inline] 2068 | fn size_hint(&self) -> (usize, Option) { 2069 | let n = if self.inner.is_some() { 1 } else { 0 }; 2070 | (n, Some(n)) 2071 | } 2072 | } 2073 | 2074 | impl<'a, T> DoubleEndedIterator for IterMut<'a, T> { 2075 | #[inline] 2076 | fn next_back(&mut self) -> Option<&'a mut T> { 2077 | self.inner.take() 2078 | } 2079 | } 2080 | 2081 | impl<'a, T> FusedIterator for IterMut<'a, T> {} 2082 | 2083 | #[cfg(feature = "nightly")] 2084 | unsafe impl<'a, T> TrustedLen for IterMut<'a, T> {} 2085 | 2086 | #[cfg(feature = "nightly")] 2087 | pub(crate) struct ResultShunt<'a, I, L, F> { 2088 | iter: I, 2089 | error: &'a mut Result<(), L, F>, 2090 | } 2091 | 2092 | #[cfg(feature = "nightly")] 2093 | #[inline] 2094 | pub(crate) fn process_results(iter: I, mut f: G) -> Result 2095 | where 2096 | I: Iterator>, 2097 | for<'a> G: FnMut(ResultShunt<'a, I, L, F>) -> U, 2098 | { 2099 | let mut error = Success(()); 2100 | let shunt = ResultShunt { 2101 | iter, 2102 | error: &mut error, 2103 | }; 2104 | let value = f(shunt); 2105 | error.map(|()| value) 2106 | } 2107 | 2108 | #[cfg(feature = "nightly")] 2109 | impl Iterator for ResultShunt<'_, I, L, F> 2110 | where 2111 | I: Iterator>, 2112 | { 2113 | type Item = T; 2114 | 2115 | #[inline] 2116 | fn next(&mut self) -> Option { 2117 | self.find(|_| true) 2118 | } 2119 | 2120 | #[inline] 2121 | fn size_hint(&self) -> (usize, Option) { 2122 | if self.error.is_err() { 2123 | (0, Some(0)) 2124 | } else { 2125 | let (_, upper) = self.iter.size_hint(); 2126 | (0, upper) 2127 | } 2128 | } 2129 | 2130 | #[inline] 2131 | fn try_fold(&mut self, init: B, mut f: G) -> R 2132 | where 2133 | G: FnMut(B, Self::Item) -> R, 2134 | R: Try, 2135 | { 2136 | let error = &mut *self.error; 2137 | 2138 | into_try(self.iter.try_fold(init, |acc, x| match x { 2139 | Success(x) => from_try(f(acc, x)), 2140 | LocalErr(l) => { 2141 | *error = LocalErr(l); 2142 | ControlFlow::Break(try { acc }) 2143 | } 2144 | FatalErr(f) => { 2145 | *error = FatalErr(f); 2146 | ControlFlow::Break(try { acc }) 2147 | } 2148 | })) 2149 | } 2150 | } 2151 | 2152 | /// Create a `ControlFlow` from any type implementing `Try`. 2153 | #[cfg(feature = "nightly")] 2154 | #[inline] 2155 | fn from_try(r: R) -> ControlFlow { 2156 | match R::branch(r) { 2157 | ControlFlow::Continue(v) => ControlFlow::Continue(v), 2158 | ControlFlow::Break(v) => ControlFlow::Break(R::from_residual(v)), 2159 | } 2160 | } 2161 | 2162 | /// Convert a `ControlFlow` into any type implementing `Try`; 2163 | #[cfg(feature = "nightly")] 2164 | #[inline] 2165 | fn into_try(cf: ControlFlow) -> R { 2166 | match cf { 2167 | ControlFlow::Continue(v) => R::from_output(v), 2168 | ControlFlow::Break(v) => v, 2169 | } 2170 | } 2171 | 2172 | impl From> for Result { 2173 | fn from(result: StdResult) -> Result { 2174 | match result { 2175 | Ok(t) => Success(t), 2176 | Err(l) => LocalErr(l), 2177 | } 2178 | } 2179 | } 2180 | 2181 | impl From, F>> for Result { 2182 | fn from(result: StdResult, F>) -> Result { 2183 | match result { 2184 | Ok(inner) => match inner { 2185 | Ok(ok) => Success(ok), 2186 | Err(err) => LocalErr(err), 2187 | }, 2188 | Err(err) => FatalErr(err), 2189 | } 2190 | } 2191 | } 2192 | 2193 | impl From> for StdResult, F> { 2194 | fn from(other: Result) -> StdResult, F> { 2195 | match other { 2196 | Success(ok) => Ok(Ok(ok)), 2197 | LocalErr(err) => Ok(Err(err)), 2198 | FatalErr(err) => Err(err), 2199 | } 2200 | } 2201 | } 2202 | 2203 | #[cfg(feature = "serde")] 2204 | impl Serialize for Result 2205 | where 2206 | T: Serialize, 2207 | L: Serialize, 2208 | F: Serialize, 2209 | { 2210 | fn serialize(&self, serializer: S) -> StdResult 2211 | where 2212 | S: Serializer, 2213 | { 2214 | // Convert `woah::Result` into `StdResult, &F>` and serialize that. 2215 | self.as_ref().into_result().serialize(serializer) 2216 | } 2217 | } 2218 | 2219 | #[cfg(feature = "serde")] 2220 | impl<'de, T, L, F> Deserialize<'de> for Result 2221 | where 2222 | T: Deserialize<'de>, 2223 | L: Deserialize<'de>, 2224 | F: Deserialize<'de>, 2225 | { 2226 | fn deserialize(deserializer: D) -> StdResult 2227 | where 2228 | D: Deserializer<'de>, 2229 | { 2230 | // Deserialize a `std::result::Result`. 2231 | let result: StdResult, F> = StdResult::deserialize(deserializer)?; 2232 | // Convert to a `woah::Result`. 2233 | let result: Result = result.into(); 2234 | // Wrap it for the return. 2235 | Ok(result) 2236 | } 2237 | } 2238 | --------------------------------------------------------------------------------