Option type which short-cirtuits on Some instead of None in Try contexts
This commit is contained in:
parent
b22254cb32
commit
b3d4159883
|
|
@ -7,6 +7,7 @@ edition = "2024"
|
|||
default = ["alloc"]
|
||||
alloc = []
|
||||
std = ["alloc"]
|
||||
transposed-option = ["nightly"]
|
||||
nightly = []
|
||||
|
||||
[dependencies]
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
#![cfg_attr(feature = "nightly", feature(strict_provenance_atomic_ptr))]
|
||||
#![cfg_attr(feature = "transposed-option", feature(try_trait_v2))]
|
||||
|
||||
#[cfg(any(test, feature = "std", feature = "alloc"))]
|
||||
extern crate alloc;
|
||||
|
|
@ -10,6 +11,8 @@ extern crate std;
|
|||
pub mod atomic;
|
||||
pub mod cachepadded;
|
||||
pub mod drop_guard;
|
||||
#[cfg(feature = "transposed-option")]
|
||||
pub mod option;
|
||||
pub mod ptr;
|
||||
pub mod rand;
|
||||
#[cfg(feature = "alloc")]
|
||||
|
|
|
|||
98
src/option.rs
Normal file
98
src/option.rs
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Default)]
|
||||
pub enum TransposedOption<T> {
|
||||
#[default]
|
||||
None,
|
||||
Some(T),
|
||||
}
|
||||
|
||||
impl<T> TransposedOption<T> {
|
||||
pub fn new(value: T) -> Self {
|
||||
TransposedOption::Some(value)
|
||||
}
|
||||
|
||||
pub fn is_none(&self) -> bool {
|
||||
matches!(self, TransposedOption::None)
|
||||
}
|
||||
|
||||
pub fn map<U, F>(self, f: F) -> TransposedOption<U>
|
||||
where
|
||||
F: FnOnce(T) -> U,
|
||||
{
|
||||
use TransposedOption::*;
|
||||
match self {
|
||||
Some(value) => Some(f(value)),
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn and_then<U, F>(self, f: F) -> TransposedOption<U>
|
||||
where
|
||||
F: FnOnce(T) -> TransposedOption<U>,
|
||||
{
|
||||
use TransposedOption::*;
|
||||
match self {
|
||||
Some(value) => f(value),
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<Option<T>> for TransposedOption<T> {
|
||||
fn from(option: Option<T>) -> Self {
|
||||
match option {
|
||||
Some(value) => TransposedOption::Some(value),
|
||||
None => TransposedOption::None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<TransposedOption<T>> for Option<T> {
|
||||
fn from(transposed: TransposedOption<T>) -> Self {
|
||||
match transposed {
|
||||
TransposedOption::Some(value) => Some(value),
|
||||
TransposedOption::None => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> core::ops::Try for TransposedOption<T> {
|
||||
type Output = TransposedOption<T>;
|
||||
type Residual = T;
|
||||
|
||||
fn from_output(_: Self::Output) -> Self {
|
||||
use TransposedOption::*;
|
||||
None
|
||||
}
|
||||
|
||||
fn branch(self) -> std::ops::ControlFlow<Self::Residual, Self::Output> {
|
||||
use TransposedOption::*;
|
||||
match self {
|
||||
Some(value) => std::ops::ControlFlow::Break(value),
|
||||
None => std::ops::ControlFlow::Continue(None),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: From<U>, U> core::ops::FromResidual<U> for TransposedOption<T> {
|
||||
fn from_residual(residual: U) -> Self {
|
||||
Self::new(residual.into())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use TransposedOption::*;
|
||||
|
||||
#[test]
|
||||
fn transposed_option_try() {
|
||||
let a: TransposedOption<i32> = try {
|
||||
TransposedOption::Some(42)?;
|
||||
None::<i32>?;
|
||||
|
||||
Some(3)
|
||||
};
|
||||
|
||||
assert_eq!(a, TransposedOption::Some(42));
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue