#![doc = include_str!("../README.md")]
#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(docsrs, feature(doc_cfg))]
#![cfg_attr(docsrs, allow(unused_attributes))]
#![deny(missing_docs)]
#[cfg(all(not(feature = "std"), feature = "alloc"))]
extern crate alloc as std;
#[cfg(feature = "std")]
extern crate std;
use core::{
borrow::{Borrow, BorrowMut},
fmt,
mem::MaybeUninit,
ops::{Deref, DerefMut},
};
pub use crate::Maybe::{Owned, Ref};
pub type MaybeRef<'a, T> = Maybe<&'a T, T>;
pub type MaybeMut<'a, T> = Maybe<&'a mut T, T>;
pub enum Maybe<R, T> {
Ref(R),
Owned(T),
}
impl<T> Borrow<T> for MaybeRef<'_, T> {
#[cfg_attr(not(tarpaulin), inline(always))]
fn borrow(&self) -> &T {
self.as_ref()
}
}
impl<T> Borrow<T> for MaybeMut<'_, T> {
#[cfg_attr(not(tarpaulin), inline(always))]
fn borrow(&self) -> &T {
self.as_ref()
}
}
impl<T> BorrowMut<T> for MaybeMut<'_, T> {
#[cfg_attr(not(tarpaulin), inline(always))]
fn borrow_mut(&mut self) -> &mut T {
self.as_mut()
}
}
impl<T> AsRef<T> for MaybeRef<'_, T> {
#[cfg_attr(not(tarpaulin), inline(always))]
fn as_ref(&self) -> &T {
match self {
Maybe::Ref(r) => r,
Maybe::Owned(t) => t,
}
}
}
impl<T> AsRef<T> for MaybeMut<'_, T> {
#[cfg_attr(not(tarpaulin), inline(always))]
fn as_ref(&self) -> &T {
match self {
Maybe::Ref(r) => r,
Maybe::Owned(t) => t,
}
}
}
impl<T> AsMut<T> for MaybeMut<'_, T> {
#[cfg_attr(not(tarpaulin), inline(always))]
fn as_mut(&mut self) -> &mut T {
match self {
Maybe::Ref(r) => r,
Maybe::Owned(t) => t,
}
}
}
impl<T> Deref for MaybeRef<'_, T> {
type Target = T;
#[cfg_attr(not(tarpaulin), inline(always))]
fn deref(&self) -> &Self::Target {
match self {
Maybe::Ref(r) => r,
Maybe::Owned(t) => t,
}
}
}
impl<T> Deref for MaybeMut<'_, T> {
type Target = T;
#[cfg_attr(not(tarpaulin), inline(always))]
fn deref(&self) -> &Self::Target {
match self {
Maybe::Ref(r) => r,
Maybe::Owned(t) => t,
}
}
}
impl<T> DerefMut for MaybeMut<'_, T> {
#[cfg_attr(not(tarpaulin), inline(always))]
fn deref_mut(&mut self) -> &mut Self::Target {
match self {
Maybe::Ref(r) => r,
Maybe::Owned(t) => t,
}
}
}
impl<T> PartialEq for MaybeRef<'_, T>
where
T: PartialEq,
{
#[cfg_attr(not(tarpaulin), inline(always))]
fn eq(&self, other: &Self) -> bool {
(**self).eq(&**other)
}
}
impl<T, O> PartialEq<&O> for MaybeRef<'_, T>
where
T: PartialEq<O>,
{
#[cfg_attr(not(tarpaulin), inline(always))]
fn eq(&self, other: &&O) -> bool {
(**self).eq(*other)
}
}
impl<T> Eq for MaybeRef<'_, T> where T: Eq {}
impl<T> PartialOrd for MaybeRef<'_, T>
where
T: PartialOrd,
{
#[cfg_attr(not(tarpaulin), inline(always))]
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
(**self).partial_cmp(&**other)
}
}
impl<T, O> PartialOrd<&O> for MaybeRef<'_, T>
where
T: PartialOrd<O>,
{
#[cfg_attr(not(tarpaulin), inline(always))]
fn partial_cmp(&self, other: &&O) -> Option<core::cmp::Ordering> {
(**self).partial_cmp(*other)
}
}
impl<T> Ord for MaybeRef<'_, T>
where
T: Ord,
{
#[cfg_attr(not(tarpaulin), inline(always))]
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
(**self).cmp(&**other)
}
}
impl<T> fmt::Display for MaybeRef<'_, T>
where
T: fmt::Display,
{
#[cfg_attr(not(tarpaulin), inline(always))]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
(**self).fmt(f)
}
}
impl<T> fmt::Debug for MaybeRef<'_, T>
where
T: fmt::Debug,
{
#[cfg_attr(not(tarpaulin), inline(always))]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
(**self).fmt(f)
}
}
impl<T> Clone for MaybeRef<'_, T>
where
T: Clone,
{
#[cfg_attr(not(tarpaulin), inline(always))]
fn clone(&self) -> Self {
match self {
Maybe::Ref(r) => Maybe::Ref(*r),
Maybe::Owned(t) => Maybe::Owned(t.clone()),
}
}
}
impl<T> Copy for MaybeRef<'_, T> where T: Copy {}
impl<T> core::hash::Hash for MaybeRef<'_, T>
where
T: core::hash::Hash,
{
#[cfg_attr(not(tarpaulin), inline(always))]
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
(**self).hash(state)
}
}
impl<R, T> Default for Maybe<R, T>
where
T: Default,
{
#[cfg_attr(not(tarpaulin), inline(always))]
fn default() -> Self {
Maybe::Owned(T::default())
}
}
impl<R, T> From<T> for Maybe<R, T> {
#[cfg_attr(not(tarpaulin), inline(always))]
fn from(value: T) -> Self {
Maybe::Owned(value)
}
}
impl<'a, T> From<&'a T> for Maybe<&'a T, T> {
#[cfg_attr(not(tarpaulin), inline(always))]
fn from(value: &'a T) -> Self {
Maybe::Ref(value)
}
}
impl<'a, T> From<&'a mut T> for Maybe<&'a mut T, T> {
#[cfg_attr(not(tarpaulin), inline(always))]
fn from(value: &'a mut T) -> Self {
Maybe::Ref(value)
}
}
impl<T> Maybe<&T, T> {
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn as_ref(&self) -> &T {
match self {
Maybe::Ref(r) => r,
Maybe::Owned(t) => t,
}
}
}
impl<T> Maybe<&mut T, T> {
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn as_mut(&mut self) -> &mut T {
match self {
Maybe::Ref(r) => r,
Maybe::Owned(t) => t,
}
}
}
impl<T> Maybe<T, T> {
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn into_inner(self) -> T {
match self {
Maybe::Ref(r) => r,
Maybe::Owned(t) => t,
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn as_inner(&self) -> &T {
match self {
Maybe::Ref(r) => r,
Maybe::Owned(t) => t,
}
}
}
impl<R, T> Maybe<R, T> {
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn is_ref(&self) -> bool {
matches!(self, Maybe::Ref(_))
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn is_owned(&self) -> bool {
matches!(self, Maybe::Owned(_))
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn map<R2, T2, F, G>(self, ref_fn: F, owned_fn: G) -> Maybe<R2, T2>
where
F: FnOnce(R) -> R2,
G: FnOnce(T) -> T2,
{
match self {
Maybe::Ref(r) => Maybe::Ref(ref_fn(r)),
Maybe::Owned(t) => Maybe::Owned(owned_fn(t)),
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn map_ref<R2, F>(self, f: F) -> Maybe<R2, T>
where
F: FnOnce(R) -> R2,
{
match self {
Maybe::Ref(r) => Maybe::Ref(f(r)),
Maybe::Owned(t) => Maybe::Owned(t),
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn map_owned<T2, F>(self, f: F) -> Maybe<R, T2>
where
F: FnOnce(T) -> T2,
{
match self {
Maybe::Ref(r) => Maybe::Ref(r),
Maybe::Owned(t) => Maybe::Owned(f(t)),
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn inspect<F, G>(self, ref_fn: F, owned_fn: G) -> Self
where
F: FnOnce(&R),
G: FnOnce(&T),
{
match &self {
Maybe::Ref(r) => ref_fn(r),
Maybe::Owned(t) => owned_fn(t),
}
self
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn unwrap_ref(self) -> R {
match self {
Maybe::Ref(r) => r,
Maybe::Owned(_) => panic!("called `Maybe::unwrap_ref()` on an `Owned` value"),
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn unwrap_owned(self) -> T {
match self {
Maybe::Ref(_) => panic!("called `Maybe::unwrap_owned()` on a `Ref` value"),
Maybe::Owned(t) => t,
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn try_unwrap_ref(self) -> Result<R, Self> {
match self {
Maybe::Ref(r) => Ok(r),
Maybe::Owned(_) => Err(self),
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn try_unwrap_owned(self) -> Result<T, Self> {
match self {
Maybe::Ref(_) => Err(self),
Maybe::Owned(t) => Ok(t),
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn expect_ref(self, msg: &str) -> R {
match self {
Maybe::Ref(r) => r,
Maybe::Owned(_) => panic!("{msg}"),
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn expect_owned(self, msg: &str) -> T {
match self {
Maybe::Ref(_) => panic!("{msg}"),
Maybe::Owned(t) => t,
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn as_maybe_ref(&self) -> Maybe<&R, &T> {
match self {
Maybe::Ref(r) => Maybe::Ref(r),
Maybe::Owned(t) => Maybe::Owned(t),
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn as_maybe_mut(&mut self) -> Maybe<&mut R, &mut T> {
match self {
Maybe::Ref(r) => Maybe::Ref(r),
Maybe::Owned(t) => Maybe::Owned(t),
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn map_into_owned(self, f: impl FnOnce(R) -> T) -> T {
match self {
Maybe::Ref(r) => f(r),
Maybe::Owned(t) => t,
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn map_into_ref<'a>(&'a self, f: impl FnOnce(&'a T) -> R) -> R
where
R: Clone,
{
match self {
Maybe::Ref(r) => r.clone(),
Maybe::Owned(t) => f(t),
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
#[cfg(any(feature = "alloc", feature = "std"))]
#[cfg_attr(docsrs, doc(cfg(any(feature = "alloc", feature = "std"))))]
pub fn into_owned(self) -> T
where
R: Deref,
R::Target: std::borrow::ToOwned<Owned = T>,
{
use std::borrow::ToOwned;
match self {
Maybe::Ref(r) => r.deref().to_owned(),
Maybe::Owned(t) => t,
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
#[cfg(any(feature = "alloc", feature = "std"))]
#[cfg_attr(docsrs, doc(cfg(any(feature = "alloc", feature = "std"))))]
pub fn to_owned(&self) -> T
where
R: Deref,
R::Target: std::borrow::ToOwned<Owned = T>,
T: Clone,
{
use std::borrow::ToOwned;
match self {
Maybe::Ref(r) => r.deref().to_owned(),
Maybe::Owned(t) => t.clone(),
}
}
}
impl<R, T> Maybe<Option<R>, Option<T>> {
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn is_none(&self) -> bool {
match self {
Self::Ref(r) => r.is_none(),
Self::Owned(t) => t.is_none(),
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn is_some(&self) -> bool {
match self {
Self::Ref(r) => r.is_some(),
Self::Owned(t) => t.is_some(),
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn as_option_ref(&self) -> Maybe<Option<&R>, Option<&T>> {
match self {
Self::Ref(r) => Maybe::Ref(r.as_ref()),
Self::Owned(t) => Maybe::Owned(t.as_ref()),
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
#[rustversion::attr(since(1.83), const)]
pub fn as_option_mut(&mut self) -> Maybe<Option<&mut R>, Option<&mut T>> {
match self {
Self::Ref(r) => Maybe::Ref(r.as_mut()),
Self::Owned(t) => Maybe::Owned(t.as_mut()),
}
}
}
impl<R, T> Maybe<R, T> {
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn uninit() -> MaybeUninit<Maybe<R, T>> {
MaybeUninit::uninit()
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn uninit_array<const N: usize>() -> [MaybeUninit<Maybe<R, T>>; N] {
[const { MaybeUninit::uninit() }; N]
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn uninit_both_ref() -> Maybe<MaybeUninit<R>, MaybeUninit<T>> {
Maybe::Ref(MaybeUninit::uninit())
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn uninit_both_owned() -> Maybe<MaybeUninit<R>, MaybeUninit<T>> {
Maybe::Owned(MaybeUninit::uninit())
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn uninit_ref() -> Maybe<MaybeUninit<R>, T> {
Maybe::Ref(MaybeUninit::uninit())
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn uninit_owned() -> Maybe<R, MaybeUninit<T>> {
Maybe::Owned(MaybeUninit::uninit())
}
}
impl<R, T> Maybe<MaybeUninit<R>, MaybeUninit<T>> {
#[cfg_attr(not(tarpaulin), inline(always))]
#[rustversion::attr(since(1.59), const)]
pub unsafe fn assume_init(self) -> Maybe<R, T> {
match self {
Self::Ref(r) => Maybe::Ref(r.assume_init()),
Self::Owned(t) => Maybe::Owned(t.assume_init()),
}
}
}
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
const _: () = {
use std::io::{BufRead, Read, Seek, Write};
impl<T> Write for MaybeMut<'_, T>
where
T: Write,
{
#[cfg_attr(not(tarpaulin), inline(always))]
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
(**self).write(buf)
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn flush(&mut self) -> std::io::Result<()> {
(**self).flush()
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn write_vectored(&mut self, bufs: &[std::io::IoSlice<'_>]) -> std::io::Result<usize> {
(**self).write_vectored(bufs)
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn write_all(&mut self, buf: &[u8]) -> std::io::Result<()> {
(**self).write_all(buf)
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn write_fmt(&mut self, args: std::fmt::Arguments<'_>) -> std::io::Result<()> {
(**self).write_fmt(args)
}
}
impl<T> Read for MaybeMut<'_, T>
where
T: Read,
{
#[cfg_attr(not(tarpaulin), inline(always))]
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
(**self).read(buf)
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn read_vectored(&mut self, bufs: &mut [std::io::IoSliceMut<'_>]) -> std::io::Result<usize> {
(**self).read_vectored(bufs)
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> std::io::Result<usize> {
(**self).read_to_end(buf)
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn read_to_string(&mut self, buf: &mut String) -> std::io::Result<usize> {
(**self).read_to_string(buf)
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn read_exact(&mut self, buf: &mut [u8]) -> std::io::Result<()> {
(**self).read_exact(buf)
}
}
impl<T> BufRead for MaybeMut<'_, T>
where
T: BufRead,
{
#[cfg_attr(not(tarpaulin), inline(always))]
fn fill_buf(&mut self) -> std::io::Result<&[u8]> {
(**self).fill_buf()
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn consume(&mut self, amt: usize) {
(**self).consume(amt)
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn read_until(&mut self, byte: u8, buf: &mut Vec<u8>) -> std::io::Result<usize> {
(**self).read_until(byte, buf)
}
#[cfg_attr(not(tarpaulin), inline(always))]
#[rustversion::since(1.83)]
fn skip_until(&mut self, byte: u8) -> std::io::Result<usize> {
(**self).skip_until(byte)
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn read_line(&mut self, buf: &mut String) -> std::io::Result<usize> {
(**self).read_line(buf)
}
}
impl<T> Seek for MaybeMut<'_, T>
where
T: Seek,
{
#[cfg_attr(not(tarpaulin), inline(always))]
fn seek(&mut self, pos: std::io::SeekFrom) -> std::io::Result<u64> {
(**self).seek(pos)
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn rewind(&mut self) -> std::io::Result<()> {
(**self).rewind()
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn stream_position(&mut self) -> std::io::Result<u64> {
(**self).stream_position()
}
#[cfg_attr(not(tarpaulin), inline(always))]
#[rustversion::since(1.80)]
fn seek_relative(&mut self, offset: i64) -> std::io::Result<()> {
(**self).seek_relative(offset)
}
}
};
#[cfg(feature = "serde")]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
const _: () = {
use serde_core::{Deserialize, Deserializer, Serialize, Serializer};
impl<T> Serialize for MaybeRef<'_, T>
where
T: Serialize,
{
#[cfg_attr(not(tarpaulin), inline(always))]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
(**self).serialize(serializer)
}
}
impl<T> Serialize for MaybeMut<'_, T>
where
T: Serialize,
{
#[cfg_attr(not(tarpaulin), inline(always))]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
(**self).serialize(serializer)
}
}
impl<'de, R, T> Deserialize<'de> for Maybe<R, T>
where
T: Deserialize<'de>,
{
#[cfg_attr(not(tarpaulin), inline(always))]
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
T::deserialize(deserializer).map(Self::Owned)
}
}
};