//! Error handling with the `Result` type.
//!
//! `Result<T, E>` `Result` is the type used for returning and propagating
//! errors. It is an enum with the variants, `Ok(T)`, representing
//! success and containing a value, and `Err(E)`, representing error
//! and containing an error value.
//!
//! Functions return `Result` whenever errors are expected and recoverable. In
//! the `std` crate, `Result` is most prominently used for `Identity`
//! interactions and cryptographic operations.
//!
//! A simple function returning `Result` might be defined and used like so:
//!
//! ```
//! enum Version {
//! Version1,
//! Version2,
//! }
//!
//! enum VersionError {
//! InvalidNumber,
//! }
//!
//! fn parse_version(version_number: u8) -> Result<Version, VersionError> {
//! match version_number {
//! 1 => Ok(Version::Version1),
//! 2 => Ok(Version::Version2),
//! _ => Err(VersionError::InvalidNumber),
//! }
//! }
//! ```
//!
//! ### Method overview
//!
//! In addition to working with pattern matching, `Result` provides a variety
//! of methods.
//!
//! ### Querying the variant
//!
//! The `is_ok` and `is_err` methods return `true` if the `Result` is
//! `Ok` or `Err`, respectively.
//!
//! `is_ok` : `Result::is_ok`
//! `is_err`: `Result::is_err`
//!
//! ### Extracting the contained value
//!
//! These methods extract the contained value in a `Result<T,E>` when it is
//! the `Ok` variant. If the `Result` is `Err`:
//!
//! * `unwrap` reverts.
//! * `unwrap_or` returns the default provided value.
//!
//! `unwrap` : `Result::unwrap`
//! `unwrap_or`: `Result::unwrap_or`
library;
use ::logging::log;
use ::revert::revert;
use ::codec::*;
use ::debug::*;
use ::ops::*;
// ANCHOR: docs_result
/// `Result` is a type that represents either success (`Ok`) or failure (`Err`).
pub enum Result<T, E> {
/// Contains the success value.
Ok: T,
/// Contains the error value.
Err: E,
}
// ANCHOR_END: docs_result
// Type implementation
//
impl<T, E> Result<T, E> {
// Querying the contained values
//
/// Returns whether a result contains a success value.
///
/// # Returns
///
/// * [bool] - Returns `true` if the result is `Ok`.
///
/// # Examples
///
/// ```sway
/// enum Error {
/// NotFound,
/// Invalid,
/// }
///
/// fn foo() {
/// let x: Result<u64, Error> = Result::Ok(42);
/// assert(x.is_ok());
///
/// let y: Result<u64, Error> = Result::Err(Error::NotFound));
/// assert(!y.is_ok());
/// }
/// ```
pub fn is_ok(self) -> bool {
match self {
Self::Ok(_) => true,
_ => false,
}
}
/// Returns whether a result contains an error value.
///
/// # Returns
///
/// * [bool] - Returns `true` if the result is `Err`.
///
/// # Examples
///
/// ```sway
/// enum Error {
/// NotFound,
/// Invalid,
/// }
///
/// fn foo() {
/// let x: Result<u64, Error> = Result::Ok(42);
/// assert(!x.is_err());
///
/// let y: Result<u64, Error> = Result::Err(Error::NotFound));
/// assert(y.is_err());
/// }
/// ```
pub fn is_err(self) -> bool {
match self {
Self::Ok(_) => false,
_ => true,
}
}
/// Returns the contained `Ok` value, consuming the `self` value.
///
/// # Additional Information
///
/// Because this function may revert, its use is generally discouraged.
/// Instead, prefer to use pattern matching and handle the `Err`
/// case explicitly.
///
/// # Returns
///
/// * [T] - The value contained by the result.
///
/// # Reverts
///
/// * Reverts if the `Result` is the `Err` variant.
///
/// # Examples
///
/// ```sway
/// enum Error {
/// NotFound,
/// Invalid,
/// }
///
/// fn foo() {
/// let x: Result<u64, Error> = Result::Ok(42);
/// assert(x.unwrap() == 42);
///
/// let y: Result<u64, Error> = Result::Err(Error::NotFound));
/// let val = y.unwrap(); // reverts
/// }
/// ```
pub fn unwrap(self) -> T {
match self {
Self::Ok(v) => v,
_ => revert(0),
}
}
/// Returns the contained `Ok` value or a provided default.
///
/// # Arguments
///
/// * `default`: [T] - The value that is the default.
///
/// # Returns
///
/// * [T] - The value of the result or the default.
///
/// # Examples
///
/// ```sway
/// enum Error {
/// NotFound,
/// Invalid,
/// }
///
/// fn foo() {
/// let x: Result<u64, Error> = Result::Ok(42);
/// assert(x.unwrap_or(69) == 42);
///
/// let y: Result<u64, Error> = Result::Err(Error::NotFound));
/// assert(y.unwrap_or(69) == 69);
/// }
/// ```
pub fn unwrap_or(self, default: T) -> T {
match self {
Self::Ok(v) => v,
Self::Err(_) => default,
}
}
/// Returns the contained `Ok` value, consuming the `self` value.
/// If the `Result` is the `Err` variant, logs the provided message, along with the error value.
///
/// # Additional Information
///
/// Because this function may revert, its use is generally discouraged.
/// Instead, prefer to use pattern matching and handle the `Err`
/// case explicitly.
///
/// # Arguments
///
/// * `msg`: [M] - The message to be logged if the `Result` is the `Err` variant.
///
/// # Returns
///
/// * [T] - The value contained by the result.
///
/// # Reverts
///
/// * Reverts if the `Result` is the `Err` variant.
///
/// # Examples
///
/// ```sway
/// enum Error {
/// NotFound,
/// Invalid,
/// }
///
/// fn foo() {
/// let x: Result<u64, Error> = Result::Ok(42);
/// assert(x.expect("X is known to be 42") == 42);
///
/// let y: Result<u64, Error> = Result::Err(Error::NotFound));
/// let val = y.expect("Testing expect"); // reverts with `("Testing Expect", "Error::NotFound")`
/// }
/// ```
///
/// # Recommended Message Style
///
/// We recommend that `expect` messages are used to describe the reason you *expect* the `Result` should be `Ok`.
///
/// ```sway
/// let x: Result<u64, Error> = bar(1);
/// let value = x.expect("bar() should never return Err with 1 as an argument");
/// ```
pub fn expect<M>(self, msg: M) -> T
where
M: AbiEncode,
E: AbiEncode,
{
match self {
Self::Ok(v) => v,
Self::Err(err) => {
log((msg, err));
revert(0);
},
}
}
// TODO: Implement the following transforms when Option and Result can
// import one another:
// - `ok(self) -> Option<T>`
// - `err(self) -> Option<E>`
}
impl<T, E> PartialEq for Result<T, E>
where
T: PartialEq,
E: PartialEq,
{
fn eq(self, other: Self) -> bool {
match (self, other) {
(Self::Ok(a), Self::Ok(b)) => a == b,
(Self::Err(a), Self::Err(b)) => a == b,
_ => false,
}
}
}
impl<T, E> Eq for Result<T, E>
where
T: Eq,
E: Eq,
{}