use std::{fmt, iter::FusedIterator};
#[must_use = "`Presence` may contain a value that should be used"]
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub enum Presence<T> {
#[doc(alias = "undefined")]
#[doc(alias = "missing")]
#[doc(alias = "none")]
#[doc(alias = "empty")]
Absent,
#[doc(alias = "nil")]
#[doc(alias = "nothing")]
#[doc(alias = "void")]
Null,
#[doc(alias = "value")]
#[doc(alias = "present")]
#[doc(alias = "defined")]
#[doc(alias = "just")]
Some(T),
}
impl<T> Presence<T> {
#[inline]
pub const fn is_absent(&self) -> bool {
matches!(self, Presence::Absent)
}
#[inline]
pub const fn is_null(&self) -> bool {
matches!(self, Presence::Null)
}
#[inline]
pub const fn is_present(&self) -> bool {
matches!(self, Presence::Some(_))
}
#[inline]
pub const fn is_defined(&self) -> bool {
!matches!(self, Presence::Absent)
}
#[inline]
pub const fn is_nullish(&self) -> bool {
!matches!(self, Presence::Some(_))
}
#[inline]
#[must_use = "Returns the converted Option"]
pub fn to_optional(self) -> Option<T> {
match self {
Presence::Some(value) => Some(value),
Presence::Null | Presence::Absent => None,
}
}
#[inline]
#[must_use = "Returns the converted nested Option"]
pub fn to_nullable(self) -> Option<Option<T>> {
match self {
Presence::Some(value) => Some(Some(value)),
Presence::Null => Some(None),
Presence::Absent => None,
}
}
#[inline]
pub fn from_optional(opt: Option<T>) -> Self {
match opt {
Some(value) => Presence::Some(value),
None => Presence::Absent,
}
}
#[inline]
pub fn from_nullable(opt: Option<Option<T>>) -> Self {
match opt {
Some(Some(value)) => Presence::Some(value),
Some(None) => Presence::Null,
None => Presence::Absent,
}
}
#[inline]
pub fn unwrap_or_null_default(self, absent_default: T, null_default: T) -> T {
match self {
Presence::Some(value) => value,
Presence::Null => null_default,
Presence::Absent => absent_default,
}
}
#[inline]
pub fn is_some_and(self, f: impl FnOnce(T) -> bool) -> bool {
match self {
Presence::Some(val) => f(val),
Presence::Null | Presence::Absent => false,
}
}
#[inline]
pub fn is_absent_or(self, f: impl FnOnce(T) -> bool) -> bool {
match self {
Presence::Some(val) => f(val),
Presence::Null => false,
Presence::Absent => true,
}
}
#[inline]
pub fn is_null_or(self, f: impl FnOnce(T) -> bool) -> bool {
match self {
Presence::Some(val) => f(val),
Presence::Null | Presence::Absent => true,
}
}
#[inline]
pub const fn as_ref(&self) -> Presence<&T> {
match *self {
Presence::Some(ref val) => Presence::Some(val),
Presence::Null => Presence::Null,
Presence::Absent => Presence::Absent,
}
}
#[inline]
pub const fn as_mut(&mut self) -> Presence<&mut T> {
match *self {
Presence::Some(ref mut val) => Presence::Some(val),
Presence::Null => Presence::Null,
Presence::Absent => Presence::Absent,
}
}
#[inline]
pub const fn as_pin_ref(self: std::pin::Pin<&Self>) -> Presence<std::pin::Pin<&T>> {
match std::pin::Pin::get_ref(self) {
Presence::Some(val) => unsafe { Presence::Some(std::pin::Pin::new_unchecked(val)) },
Presence::Null => Presence::Null,
Presence::Absent => Presence::Absent,
}
}
#[inline]
pub const fn as_pin_mut(self: std::pin::Pin<&mut Self>) -> Presence<std::pin::Pin<&mut T>> {
unsafe {
match std::pin::Pin::get_unchecked_mut(self) {
Presence::Some(val) => Presence::Some(std::pin::Pin::new_unchecked(val)),
Presence::Null => Presence::Null,
Presence::Absent => Presence::Absent,
}
}
}
#[inline]
pub const fn as_slice(&self) -> &[T] {
match self {
Presence::Some(val) => std::slice::from_ref(val),
Presence::Null | Presence::Absent => &[],
}
}
#[inline]
pub fn as_mut_slice(&mut self) -> &mut [T] {
match self {
Presence::Some(val) => std::slice::from_mut(val),
Presence::Null | Presence::Absent => &mut [],
}
}
#[inline]
pub fn as_deref(&self) -> Presence<&T::Target>
where
T: std::ops::Deref,
{
match self.as_ref() {
Presence::Some(val) => Presence::Some(val.deref()),
Presence::Null => Presence::Null,
Presence::Absent => Presence::Absent,
}
}
#[inline]
pub fn as_deref_mut(&mut self) -> Presence<&mut T::Target>
where
T: std::ops::DerefMut,
{
match self.as_mut() {
Presence::Some(val) => Presence::Some(val.deref_mut()),
Presence::Null => Presence::Null,
Presence::Absent => Presence::Absent,
}
}
#[inline]
pub fn to_nested_option(self) -> Option<Option<T>> {
match self {
Presence::Absent => None,
Presence::Null => Some(None),
Presence::Some(val) => Some(Some(val)),
}
}
#[inline]
#[track_caller]
pub fn expect(self, msg: &str) -> T {
match self {
Presence::Some(val) => val,
Presence::Null => panic!("{}: value was Null", msg),
Presence::Absent => panic!("{}: value was Absent", msg),
}
}
#[inline]
#[track_caller]
pub fn unwrap(self) -> T {
match self {
Presence::Some(val) => val,
Presence::Null => panic!("called `Presence::unwrap()` on a `Null` value"),
Presence::Absent => panic!("called `Presence::unwrap()` on an `Absent` value"),
}
}
#[inline]
#[must_use = "if you don't need the returned value, use `if let` or `match` instead"]
pub fn unwrap_or(self, default: T) -> T {
match self {
Presence::Some(val) => val,
Presence::Null | Presence::Absent => default,
}
}
#[inline]
#[must_use = "If you don't need the returned value, use `if let` or `match` instead"]
pub fn unwrap_or_else<F>(self, f: F) -> T
where
F: FnOnce() -> T,
{
match self {
Presence::Some(val) => val,
Presence::Null | Presence::Absent => f(),
}
}
#[inline]
#[must_use = "If you don't need the returned value, use `if let` or `match` instead"]
pub fn unwrap_or_default(self) -> T
where
T: Default,
{
match self {
Presence::Some(val) => val,
Presence::Null | Presence::Absent => Default::default(),
}
}
#[inline]
pub const fn take(&mut self) -> Presence<T> {
let mut slot = Presence::Absent;
std::mem::swap(self, &mut slot);
slot
}
#[inline]
pub fn take_if<P>(&mut self, predicate: P) -> Presence<T>
where
P: FnOnce(&T) -> bool,
{
match self {
Presence::Some(val) if predicate(val) => self.take(),
_ => Presence::Absent,
}
}
#[inline]
pub fn replace(&mut self, value: T) -> Presence<T> {
std::mem::replace(self, Presence::Some(value))
}
#[inline]
pub fn insert(&mut self, value: T) -> &mut T {
*self = Presence::Some(value);
match self {
Presence::Some(v) => v,
_ => unreachable!(),
}
}
#[inline]
pub fn get_or_insert(&mut self, value: T) -> &mut T {
if matches!(self, Presence::Null | Presence::Absent) {
*self = Presence::Some(value);
}
match self {
Presence::Some(v) => v,
_ => unreachable!(),
}
}
#[inline]
pub fn get_or_insert_default(&mut self) -> &mut T
where
T: Default,
{
self.get_or_insert_with(Default::default)
}
#[inline]
pub fn get_or_insert_with<F>(&mut self, f: F) -> &mut T
where
F: FnOnce() -> T,
{
if matches!(self, Presence::Null | Presence::Absent) {
*self = Presence::Some(f());
}
match self {
Presence::Some(v) => v,
_ => unreachable!(),
}
}
#[inline]
pub const fn len(&self) -> usize {
match self {
Presence::Some(_) => 1,
Presence::Null | Presence::Absent => 0,
}
}
#[inline]
pub const fn is_empty(&self) -> bool {
matches!(self, Presence::Null | Presence::Absent)
}
#[inline]
#[must_use = "Returns the mapped value"]
pub fn map<U, F>(self, f: F) -> Presence<U>
where
F: FnOnce(T) -> U,
{
match self {
Presence::Some(val) => Presence::Some(f(val)),
Presence::Null => Presence::Null,
Presence::Absent => Presence::Absent,
}
}
#[inline]
pub fn inspect<F>(self, f: F) -> Self
where
F: FnOnce(&T),
{
if let Presence::Some(ref val) = self {
f(val);
}
self
}
#[inline]
#[must_use = "Returns the mapped value or default"]
pub fn map_or<U, F>(self, default: U, f: F) -> U
where
F: FnOnce(T) -> U,
{
match self {
Presence::Some(val) => f(val),
Presence::Null | Presence::Absent => default,
}
}
#[inline]
#[must_use = "Returns the mapped value or computed default"]
pub fn map_or_else<U, D, F>(self, default: D, f: F) -> U
where
D: FnOnce() -> U,
F: FnOnce(T) -> U,
{
match self {
Presence::Some(val) => f(val),
Presence::Null | Presence::Absent => default(),
}
}
#[inline]
pub fn map_or_default<U, F>(self, f: F) -> U
where
F: FnOnce(T) -> U,
U: Default,
{
match self {
Presence::Some(val) => f(val),
Presence::Null | Presence::Absent => Default::default(),
}
}
#[inline]
pub fn ok_or<E>(self, err: E) -> Result<T, E> {
match self {
Presence::Some(val) => Ok(val),
Presence::Null | Presence::Absent => Err(err),
}
}
#[inline]
pub fn ok_or_else<E, F>(self, err: F) -> Result<T, E>
where
F: FnOnce() -> E,
{
match self {
Presence::Some(val) => Ok(val),
Presence::Null | Presence::Absent => Err(err()),
}
}
#[inline]
#[must_use = "Returns the logical AND result"]
pub fn and<U>(self, optb: Presence<U>) -> Presence<U> {
match self {
Presence::Some(_) => optb,
Presence::Null => Presence::Null,
Presence::Absent => Presence::Absent,
}
}
#[inline]
#[must_use = "Returns the result of the closure"]
pub fn and_then<U, F>(self, f: F) -> Presence<U>
where
F: FnOnce(T) -> Presence<U>,
{
match self {
Presence::Some(val) => f(val),
Presence::Null => Presence::Null,
Presence::Absent => Presence::Absent,
}
}
#[inline]
#[must_use = "Returns the filtered value"]
pub fn filter<P>(self, predicate: P) -> Self
where
P: FnOnce(&T) -> bool,
{
match self {
Presence::Some(ref val) if predicate(val) => self,
Presence::Some(_) => Presence::Absent,
Presence::Null => Presence::Null,
Presence::Absent => Presence::Absent,
}
}
#[inline]
#[must_use = "Returns the logical OR result"]
pub fn or(self, optb: Presence<T>) -> Presence<T> {
match self {
Presence::Some(_) => self,
Presence::Null | Presence::Absent => optb,
}
}
#[inline]
#[must_use = "Returns the value or computed alternative"]
pub fn or_else<F>(self, f: F) -> Presence<T>
where
F: FnOnce() -> Presence<T>,
{
match self {
Presence::Some(_) => self,
Presence::Null | Presence::Absent => f(),
}
}
#[inline]
#[must_use = "Returns the logical XOR result"]
pub fn xor(self, optb: Presence<T>) -> Presence<T> {
match (self, optb) {
(Presence::Some(a), Presence::Null | Presence::Absent) => Presence::Some(a),
(Presence::Null | Presence::Absent, Presence::Some(b)) => Presence::Some(b),
(Presence::Some(_), Presence::Some(_)) => Presence::Absent,
(Presence::Absent, _) | (_, Presence::Absent) => Presence::Absent,
(Presence::Null, Presence::Null) => Presence::Null,
}
}
#[inline]
#[must_use = "this returns the zipped tuple, without modifying the originals"]
pub fn zip<U>(self, other: Presence<U>) -> Presence<(T, U)> {
match (self, other) {
(Presence::Some(a), Presence::Some(b)) => Presence::Some((a, b)),
(Presence::Absent, _) | (_, Presence::Absent) => Presence::Absent,
(Presence::Null, _) | (_, Presence::Null) => Presence::Null,
}
}
#[inline]
pub fn zip_with<U, F, R>(self, other: Presence<U>, f: F) -> Presence<R>
where
F: FnOnce(T, U) -> R,
{
match (self, other) {
(Presence::Some(a), Presence::Some(b)) => Presence::Some(f(a, b)),
(Presence::Absent, _) | (_, Presence::Absent) => Presence::Absent,
(Presence::Null, _) | (_, Presence::Null) => Presence::Null,
}
}
#[inline]
pub fn reduce<U, R, F>(self, other: Presence<U>, f: F) -> Presence<R>
where
F: FnOnce(T, U) -> R,
{
self.zip_with(other, f)
}
#[inline]
pub fn unzip<A, B>(self) -> (Presence<A>, Presence<B>)
where
T: Into<(A, B)>,
{
match self {
Presence::Some(val) => {
let (a, b) = val.into();
(Presence::Some(a), Presence::Some(b))
}
Presence::Null => (Presence::Null, Presence::Null),
Presence::Absent => (Presence::Absent, Presence::Absent),
}
}
#[inline]
pub const fn iter(&self) -> Iter<'_, T> {
Iter {
inner: Item {
presence: self.as_ref(),
},
}
}
#[inline]
pub fn iter_mut(&mut self) -> IterMut<'_, T> {
IterMut {
inner: Item {
presence: self.as_mut(),
},
}
}
}
impl<T, E> Presence<Result<T, E>> {
#[inline]
#[must_use = "this returns the transposed result, without modifying the original"]
pub fn transpose(self) -> Result<Presence<T>, E> {
match self {
Presence::Some(Ok(v)) => Ok(Presence::Some(v)),
Presence::Some(Err(e)) => Err(e),
Presence::Null => Ok(Presence::Null),
Presence::Absent => Ok(Presence::Absent),
}
}
}
impl<T: fmt::Display> fmt::Display for Presence<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Presence::Absent => write!(f, "(absent)"),
Presence::Null => write!(f, "null"),
Presence::Some(val) => write!(f, "{}", val),
}
}
}
impl<T> Default for Presence<T> {
fn default() -> Presence<T> {
Presence::Absent
}
}
impl<T> IntoIterator for Presence<T> {
type Item = T;
type IntoIter = Item<T>;
fn into_iter(self) -> Self::IntoIter {
Item { presence: self }
}
}
#[derive(Clone, Debug)]
pub struct Item<A> {
presence: Presence<A>,
}
impl<A> Iterator for Item<A> {
type Item = A;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
match self.presence.take() {
Presence::Some(val) => Some(val),
Presence::Null | Presence::Absent => None,
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.len();
(len, Some(len))
}
}
impl<A> DoubleEndedIterator for Item<A> {
#[inline]
fn next_back(&mut self) -> Option<Self::Item> {
match self.presence.take() {
Presence::Some(val) => Some(val),
Presence::Null | Presence::Absent => None,
}
}
}
impl<A> ExactSizeIterator for Item<A> {
#[inline]
fn len(&self) -> usize {
self.presence.len()
}
}
impl<A> FusedIterator for Item<A> {}
#[derive(Debug, Clone)]
pub struct Iter<'a, A> {
inner: Item<&'a A>,
}
impl<'a, A> Iterator for Iter<'a, A> {
type Item = &'a A;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.inner.next()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
}
impl<'a, A> DoubleEndedIterator for Iter<'a, A> {
#[inline]
fn next_back(&mut self) -> Option<Self::Item> {
self.inner.next_back()
}
}
impl<'a, A> ExactSizeIterator for Iter<'a, A> {
#[inline]
fn len(&self) -> usize {
self.inner.len()
}
}
impl<A> FusedIterator for Iter<'_, A> {}
#[derive(Debug)]
pub struct IterMut<'a, A> {
inner: Item<&'a mut A>,
}
impl<'a, A> Iterator for IterMut<'a, A> {
type Item = &'a mut A;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.inner.next()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
}
impl<'a, A> DoubleEndedIterator for IterMut<'a, A> {
#[inline]
fn next_back(&mut self) -> Option<Self::Item> {
self.inner.next_back()
}
}
impl<'a, A> ExactSizeIterator for IterMut<'a, A> {
#[inline]
fn len(&self) -> usize {
self.inner.len()
}
}
impl<A> FusedIterator for IterMut<'_, A> {}
impl<T> Presence<&T> {
#[inline]
pub const fn copied(self) -> Presence<T>
where
T: Copy,
{
match self {
Presence::Some(&val) => Presence::Some(val),
Presence::Null => Presence::Null,
Presence::Absent => Presence::Absent,
}
}
#[inline]
pub fn cloned(self) -> Presence<T>
where
T: Clone,
{
match self {
Presence::Some(val) => Presence::Some(val.clone()),
Presence::Null => Presence::Null,
Presence::Absent => Presence::Absent,
}
}
}
impl<T> Presence<&mut T> {
#[inline]
pub const fn copied(self) -> Presence<T>
where
T: Copy,
{
match self {
Presence::Some(&mut val) => Presence::Some(val),
Presence::Null => Presence::Null,
Presence::Absent => Presence::Absent,
}
}
#[inline]
pub fn cloned(self) -> Presence<T>
where
T: Clone,
{
match self {
Presence::Some(val) => Presence::Some(val.clone()),
Presence::Null => Presence::Null,
Presence::Absent => Presence::Absent,
}
}
}
impl<T> Presence<Presence<T>> {
#[inline]
#[must_use = "Returns the flattened value"]
pub fn flatten(self) -> Presence<T> {
match self {
Presence::Some(inner) => inner,
Presence::Null => Presence::Null,
Presence::Absent => Presence::Absent,
}
}
}
impl<A, V: FromIterator<A>> FromIterator<Presence<A>> for Presence<V> {
fn from_iter<I: IntoIterator<Item = Presence<A>>>(iter: I) -> Self {
let mut has_null = false;
let mut values = Vec::new();
for item in iter {
match item {
Presence::Absent => return Presence::Absent,
Presence::Null => has_null = true,
Presence::Some(value) => values.push(value),
}
}
if has_null {
Presence::Null
} else {
Presence::Some(values.into_iter().collect())
}
}
}
impl<T, U> std::iter::Product<Presence<U>> for Presence<T>
where
T: std::iter::Product<U>,
{
fn product<I: Iterator<Item = Presence<U>>>(iter: I) -> Self {
let mut has_null = false;
let mut values = Vec::new();
for item in iter {
match item {
Presence::Absent => return Presence::Absent,
Presence::Null => has_null = true,
Presence::Some(value) => values.push(value),
}
}
if has_null {
Presence::Null
} else {
Presence::Some(values.into_iter().product())
}
}
}
impl<T, U> std::iter::Sum<Presence<U>> for Presence<T>
where
T: std::iter::Sum<U>,
{
fn sum<I: Iterator<Item = Presence<U>>>(iter: I) -> Self {
let mut has_null = false;
let mut values = Vec::new();
for item in iter {
match item {
Presence::Absent => return Presence::Absent,
Presence::Null => has_null = true,
Presence::Some(value) => values.push(value),
}
}
if has_null {
Presence::Null
} else {
Presence::Some(values.into_iter().sum())
}
}
}
impl<T> From<T> for Presence<T> {
#[inline]
fn from(value: T) -> Self {
Presence::Some(value)
}
}
impl<T> From<Option<Option<T>>> for Presence<T> {
#[inline]
fn from(opt: Option<Option<T>>) -> Self {
match opt {
None => Presence::Absent,
Some(None) => Presence::Null,
Some(Some(value)) => Presence::Some(value),
}
}
}
impl<T> From<Presence<T>> for Option<Option<T>> {
#[inline]
fn from(presence: Presence<T>) -> Self {
match presence {
Presence::Absent => None,
Presence::Null => Some(None),
Presence::Some(value) => Some(Some(value)),
}
}
}