unsure 0.1.0

A Rust library for handling unsure (optional) values that might fail, with an additional rejection variant.
Documentation
//! unsure.rs - implements a custom [`Unsure<T>`] enum which is essentially
//! [`Option<T>`] with an additional `Reject` variant, for handling values that
//! are deemed to be wholly negative rather than undefined.
//!
//! Uses Haskell variant names, so as to not conflict with Rust's `Option` enum,
//! which is defined globally across every Rust program.
//!
//! It's sort of like [`Option<T>`] with a [`Result<T, E>`] twist. Although it's
//! really just an [`Option<T>`] with two [`None`]-adjacent variants.
//!
//! This file is part of [unsure-rs](https://codeberg.org/AeriaVelocity/unsure-rs).
//!
//! (c) 2025 Arsalan "Aeri" Kazmi <https://aeriavelocity.dev>
//!
//! ```rust
//! // It's recommended to use the wildcard import so you don't have to type out
//! // `unsure::Unsure::` every single time you want to use a variant.
//! use unsure::Unsure::{self, *};
//!
//! fn main() {
//!     let unsure_value: Unsure<i32> = some_function_that_might_fail();
//!
//!     match unsure_value {
//!         Just(value) => println!("Value: {}", value),
//!         Nothing => eprintln!("The function returned nothing"),
//!         Reject => eprintln!("The function rejected the request"),
//!     }
//! }
//! ```
//!
//! unsure.rs is free software: you can redistribute it and/or modify
//! it under the terms of the GNU General Public License as published by
//! the Free Software Foundation, either version 3 of the License, or
//! (at your option) any later version.
//!
//! unsure.rs is distributed in the hope that it will be useful,
//! but WITHOUT ANY WARRANTY; without even the implied warranty of
//! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//! GNU General Public License for more details.
//!
//! You should have received a copy of the GNU General Public License
//! along with unsure.rs. If not, see
//! <https://www.gnu.org/licenses/gpl-3.0.html>.

/// The `Unsure` type. Used to handle a potential failure where there would
/// otherwise be an `Option`.
pub enum Unsure<T> {
    /// An erroneous or unwanted value, used to mark a situation where an unsure
    /// state should be rejected or cancelled.
    ///
    /// This is the main reason you should want to use this enum over [`Option`].
    /// If you don't need to handle failure states separately from nil or
    /// unhandled states, just use [`Option`].
    Reject,
    /// No value, like [`None`], used to mark a situation where an unsure state
    /// should be ignored or skipped.
    ///
    /// Takes its name after Haskell's `Nothing` variant of the `Maybe` type.
    Nothing,
    /// Some value of type `T`, like [`Some`], used to confirm that an unsure
    /// state is valid and confirmed.
    ///
    /// Takes its name after Haskell's `Just a` variant of the `Maybe` type.
    Just(T),
}

use Unsure::*;

impl<T> Unsure<T> {
    /// Returns `true` if the value is `[Reject]`.
    pub const fn is_reject(&self) -> bool {
        matches!(self, Reject)
    }

    /// Returns `true` if the value is [`Nothing`].
    pub const fn is_nothing(&self) -> bool {
        matches!(self, Nothing)
    }

    /// Returns `true` if the value is [`Just`].
    pub const fn is_just(&self) -> bool {
        matches!(self, Just(_))
    }

    /// Returns a reference to the value if it is [`Just`], otherwise `None`
    pub const fn as_ref(&self) -> Option<&T> {
        match self {
            Just(value) => Some(value),
            _ => None,
        }
    }

    /// Returns a mutable reference to the value if it is [`Just`], otherwise `None`
    pub const fn as_mut(&mut self) -> Option<&mut T> {
        match self {
            Just(value) => Some(value),
            _ => None,
        }
    }
}

impl<T> From<Option<T>> for Unsure<T> {
    /// Convert an `Option<T>` into an `Unsure<T>`.
    /// [`Some`] is directly mapped onto [`Just`], and [`None`] is mapped onto [`Nothing`].
    fn from(opt: Option<T>) -> Self {
        match opt {
            Some(value) => Just(value),
            None => Nothing,
        }
    }
}