#![no_std]
#![cfg_attr(feature = "try", feature(try_trait_v2))]
#[cfg(feature = "try")]
use core::ops::{ControlFlow, FromResidual, Try};
pub use Finalizable::*;
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub enum Finalizable<T> {
Working(T),
Finalized(T),
}
impl<T> Finalizable<T> {
pub fn new(value: T, finalized: bool) -> Self {
match finalized {
true => Finalized(value),
false => Working(value),
}
}
pub fn finalize(self) -> Self {
Finalized(self.get())
}
pub fn get(self) -> T {
match self {
Working(x) => x,
Finalized(x) => x,
}
}
pub fn get_as_ref(&self) -> &T {
self.as_ref().get()
}
pub fn try_get_mut(&mut self) -> Option<&mut T> {
match self {
Working(x) => Some(x),
Finalized(_) => None,
}
}
pub fn set(self, value: T) -> Self {
match self {
Working(_) => Working(value),
a @ Finalized(_) => a,
}
}
pub fn is_working(&self) -> bool {
matches!(self, Working(_))
}
pub fn is_finalized(&self) -> bool {
matches!(self, Finalized(_))
}
pub fn working_or_none(self) -> Option<T> {
match self {
Working(x) => Some(x),
Finalized(_) => None,
}
}
pub fn finalized_or_none(self) -> Option<T> {
match self {
Working(_) => None,
Finalized(x) => Some(x),
}
}
pub fn finalized_or(self, default: T) -> T {
match self {
Working(_) => default,
Finalized(x) => x,
}
}
pub fn finalized_or_else<F: FnOnce(T) -> T>(self, op: F) -> T {
match self {
Working(x) => op(x),
Finalized(x) => x,
}
}
pub fn as_ref(&self) -> Finalizable<&T> {
match self {
Working(x) => Working(x),
Finalized(x) => Finalized(x),
}
}
pub fn map<F: FnOnce(T) -> T>(self, op: F) -> Self {
match self {
Working(x) => Working(op(x)),
a @ Finalized(_) => a,
}
}
pub fn map_and_finalize<F: FnOnce(T) -> T>(self, op: F) -> Self {
self.map(op).finalize()
}
pub fn expect_finalized(self, msg: &str) -> T {
match self {
Working(x) => x,
Finalized(_) => panic!("{}", msg),
}
}
pub fn and(self, fin: Self) -> Self {
match self {
Working(_) => fin,
a @ Finalized(_) => a,
}
}
pub fn and_then<F: FnOnce(T) -> Self>(self, op: F) -> Self {
match self {
Working(x) => op(x),
a @ Finalized(_) => a,
}
}
pub fn and_then_new<F: FnOnce(T) -> (T, bool)>(self, op: F) -> Self {
self.and_then(|x| {
let (value, finalized) = op(x);
Finalizable::new(value, finalized)
})
}
}
impl<T> Finalizable<&T> {
pub fn copied(self) -> Finalizable<T>
where
T: Copy,
{
match self {
Working(x) => Working(*x),
Finalized(x) => Finalized(*x),
}
}
pub fn cloned(self) -> Finalizable<T>
where
T: Clone,
{
match self {
Working(x) => Working(x.clone()),
Finalized(x) => Finalized(x.clone()),
}
}
}
#[cfg(feature = "try")]
impl<T> Try for Finalizable<T> {
type Output = T;
type Residual = Residual<T>;
fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
match self {
Working(x) => ControlFlow::Continue(x),
Finalized(x) => ControlFlow::Break(Residual(x)),
}
}
fn from_output(output: Self::Output) -> Self {
Working(output)
}
}
#[cfg(feature = "try")]
impl<T> FromResidual for Finalizable<T> {
fn from_residual(residual: <Self as Try>::Residual) -> Self {
Finalized(residual.0)
}
}
#[cfg(feature = "try")]
pub struct Residual<T>(pub T);