#![deny(missing_docs)]
#![deny(unsafe_code)]
#[cfg(feature = "serde")]
extern crate serde;
use std::slice::Iter;
use std::cmp::Ordering;
use std::convert::From;
use std::iter::Iterator;
use std::mem;
use std::ops::{Deref, Index, RangeFull};
use std::fmt::{self, Debug, Error};
use std::hash::{Hash, Hasher};
use self::OptionBool::*;
#[derive(Copy, Clone, PartialEq, Eq, Ord, Hash)]
pub enum OptionBool {
SomeTrue,
SomeFalse,
None,
}
const OB_SOME_TRUE: Option<bool> = Option::Some(true);
const OB_SOME_FALSE: Option<bool> = Option::Some(false);
const OB_NONE: Option<bool> = Option::None;
const OB_SOME_TRUE_REF: &'static Option<bool> = &OB_SOME_TRUE;
const OB_SOME_FALSE_REF: &'static Option<bool> = &OB_SOME_FALSE;
const OB_NONE_REF: &'static Option<bool> = &OB_NONE;
impl Deref for OptionBool {
type Target = Option<bool>;
#[inline]
fn deref(&self) -> &'static Option<bool> {
match *self {
SomeTrue => OB_SOME_TRUE_REF,
SomeFalse => OB_SOME_FALSE_REF,
None => OB_NONE_REF,
}
}
}
impl<'a> PartialEq<OptionBool> for &'a OptionBool {
#[inline]
fn eq(&self, other: &OptionBool) -> bool {
match (*self, other) {
(&SomeTrue, &SomeTrue) | (&SomeFalse, &SomeFalse) | (&None, &None) => true,
_ => false,
}
}
}
impl Index<RangeFull> for OptionBool {
type Output = [bool];
#[inline]
fn index<'a>(&'a self, _: RangeFull) -> &'static [bool] {
match *self {
SomeTrue => OB_TRUE_SLICE_REF,
SomeFalse => OB_FALSE_SLICE_REF,
None => OB_EMPTY_SLICE_REF,
}
}
}
impl PartialOrd for OptionBool {
#[inline]
fn partial_cmp(&self, other: &OptionBool) -> Option<Ordering> {
match (self, other) {
(&SomeTrue, &SomeTrue) | (&SomeFalse, &SomeFalse) | (&None, &None) => {
Option::Some(Ordering::Equal)
}
(&SomeTrue, &SomeFalse) | (&SomeTrue, &None) | (&SomeFalse, &None) => {
Option::Some(Ordering::Greater)
}
_ => Option::Some(Ordering::Less),
}
}
}
static OB_TRUE_SLICE: [bool; 1] = [true];
static OB_FALSE_SLICE: [bool; 1] = [false];
static OB_EMPTY_SLICE: [bool; 0] = [];
static OB_TRUE_SLICE_REF: &'static [bool] = &OB_TRUE_SLICE;
static OB_FALSE_SLICE_REF: &'static [bool] = &OB_FALSE_SLICE;
static OB_EMPTY_SLICE_REF: &'static [bool] = &OB_EMPTY_SLICE;
#[cfg(feature = "serde")]
impl<'de> serde::Deserialize<'de> for OptionBool {
fn deserialize<D>(deserializer: D) -> Result<OptionBool, D::Error>
where
D: serde::Deserializer<'de>,
{
Option::<bool>::deserialize(deserializer).map(OptionBool::from)
}
}
#[cfg(feature = "serde")]
impl serde::Serialize for OptionBool {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
Option::<bool>::from(*self).serialize(serializer)
}
}
impl OptionBool {
#[inline]
pub fn some(b: bool) -> Self {
if b {
SomeTrue
} else {
SomeFalse
}
}
#[inline]
pub fn none() -> Self {
None
}
#[inline]
pub fn is_some(&self) -> bool {
if let OptionBool::None = *self {
false
} else {
true
}
}
#[inline]
pub fn is_none(&self) -> bool {
if let OptionBool::None = *self {
true
} else {
false
}
}
#[inline]
pub fn expect(&self, msg: &str) -> bool {
match *self {
SomeTrue => true,
SomeFalse => false,
None => panic!("{}", msg),
}
}
#[inline]
pub fn unwrap(&self) -> bool {
self.expect("unwrap called on None")
}
#[inline]
pub fn unwrap_or(&self, def: bool) -> bool {
match *self {
SomeTrue => true,
SomeFalse => false,
None => def,
}
}
#[inline]
pub fn unwrap_or_else<F>(self, f: F) -> bool
where
F: FnOnce() -> bool,
{
match self {
SomeTrue => true,
SomeFalse => false,
None => f(),
}
}
#[inline]
pub fn map<U, F>(self, f: F) -> Option<U>
where
F: FnOnce(bool) -> U,
{
match self {
SomeTrue => Option::Some(f(true)),
SomeFalse => Option::Some(f(false)),
None => Option::None,
}
}
#[inline]
pub fn map_bool<F>(self, f: F) -> OptionBool
where
F: FnOnce(bool) -> bool,
{
match self {
SomeTrue => if f(true) {
SomeTrue
} else {
SomeFalse
},
SomeFalse => if f(false) {
SomeTrue
} else {
SomeFalse
},
None => None,
}
}
#[inline]
pub fn map_or<U, F>(self, default: U, f: F) -> U
where
F: FnOnce(bool) -> U,
{
match self {
SomeTrue => f(true),
SomeFalse => f(false),
None => default,
}
}
#[inline]
pub fn map_or_else<U, D, F>(self, default: D, f: F) -> U
where
D: FnOnce() -> U,
F: FnOnce(bool) -> U,
{
match self {
SomeTrue => f(true),
SomeFalse => f(false),
None => default(),
}
}
#[inline]
pub fn ok_or<E>(self, err: E) -> Result<bool, E> {
match self {
SomeTrue => Ok(true),
SomeFalse => Ok(false),
None => Err(err),
}
}
#[inline]
pub fn ok_or_else<E, F>(self, err: F) -> Result<bool, E>
where
F: FnOnce() -> E,
{
match self {
SomeTrue => Ok(true),
SomeFalse => Ok(false),
None => Err(err()),
}
}
#[inline]
pub fn and<U>(self, optb: Option<U>) -> Option<U> {
match self {
SomeTrue | SomeFalse => optb,
None => Option::None,
}
}
#[inline]
pub fn and_bool(self, optb: OptionBool) -> OptionBool {
match self {
None => None,
_ => optb,
}
}
#[inline]
pub fn and_then<U, F>(self, f: F) -> Option<U>
where
F: FnOnce(bool) -> Option<U>,
{
match self {
SomeTrue => f(true),
SomeFalse => f(false),
None => Option::None,
}
}
#[inline]
pub fn and_then_bool<F>(self, f: F) -> OptionBool
where
F: FnOnce(bool) -> OptionBool,
{
match self {
SomeTrue => f(true),
SomeFalse => f(false),
None => None,
}
}
#[inline]
pub fn or(self, optb: Option<bool>) -> Option<bool> {
match self {
SomeTrue => Some(true),
SomeFalse => Some(false),
None => optb,
}
}
#[inline]
pub fn or_bool(self, optb: OptionBool) -> OptionBool {
match self {
None => optb,
x => x,
}
}
#[inline]
pub fn or_else<F>(self, f: F) -> Option<bool>
where
F: FnOnce() -> Option<bool>,
{
match self {
SomeTrue => Option::Some(true),
SomeFalse => Option::Some(false),
None => f(),
}
}
#[inline]
pub fn or_else_bool<F>(self, f: F) -> OptionBool
where
F: FnOnce() -> OptionBool,
{
match self {
None => f(),
x => x,
}
}
#[inline]
pub fn iter(&self) -> Iter<bool> {
self.as_slice().iter()
}
#[inline]
pub fn as_slice(self) -> &'static [bool] {
match self {
SomeTrue => OB_TRUE_SLICE_REF,
SomeFalse => OB_FALSE_SLICE_REF,
None => OB_EMPTY_SLICE_REF,
}
}
#[inline]
pub fn take(&mut self) -> Option<bool> {
self.take_bool().into()
}
#[inline]
pub fn take_bool(&mut self) -> OptionBool {
mem::replace(self, None)
}
}
impl Debug for OptionBool {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), Error> {
write!(
f,
"{}",
match *self {
SomeTrue => "Some(true)",
SomeFalse => "Some(false)",
None => "None",
}
)
}
}
pub struct IterBool {
o: OptionBool,
}
impl Iterator for IterBool {
type Item = bool;
#[inline]
fn next(&mut self) -> Option<bool> {
self.o.take()
}
}
impl IntoIterator for OptionBool {
type Item = bool;
type IntoIter = IterBool;
#[inline]
fn into_iter(self) -> IterBool {
IterBool { o: self }
}
}
impl Default for OptionBool {
#[inline]
fn default() -> OptionBool {
None
}
}
impl From<OptionBool> for Option<bool> {
#[inline]
fn from(o: OptionBool) -> Option<bool> {
match o {
SomeTrue => Option::Some(true),
SomeFalse => Option::Some(false),
None => Option::None,
}
}
}
impl<'a> From<&'a OptionBool> for Option<bool> {
#[inline]
fn from(o: &'a OptionBool) -> Option<bool> {
match *o {
SomeTrue => Option::Some(true),
SomeFalse => Option::Some(false),
None => Option::None,
}
}
}
impl From<Option<bool>> for OptionBool {
#[inline]
fn from(o: Option<bool>) -> Self {
match o {
Option::Some(true) => SomeTrue,
Option::Some(false) => SomeFalse,
Option::None => None,
}
}
}
impl<'a> From<&'a Option<bool>> for OptionBool {
#[inline]
fn from(o: &'a Option<bool>) -> Self {
match *o {
Option::Some(true) => SomeTrue,
Option::Some(false) => SomeFalse,
Option::None => None,
}
}
}
pub trait Noned {
fn is_none(&self) -> bool;
fn get_none() -> Self;
}
impl Noned for u8 {
#[inline]
fn is_none(&self) -> bool {
self == &std::u8::MAX
}
#[inline]
fn get_none() -> u8 {
std::u8::MAX
}
}
impl Noned for u16 {
#[inline]
fn is_none(&self) -> bool {
self == &std::u16::MAX
}
#[inline]
fn get_none() -> u16 {
std::u16::MAX
}
}
impl Noned for u32 {
#[inline]
fn is_none(&self) -> bool {
self == &std::u32::MAX
}
#[inline]
fn get_none() -> u32 {
std::u32::MAX
}
}
impl Noned for u64 {
#[inline]
fn is_none(&self) -> bool {
self == &std::u64::MAX
}
#[inline]
fn get_none() -> u64 {
std::u64::MAX
}
}
impl Noned for usize {
#[inline]
fn is_none(&self) -> bool {
self == &std::usize::MAX
}
#[inline]
fn get_none() -> usize {
std::usize::MAX
}
}
impl Noned for i8 {
#[inline]
fn is_none(&self) -> bool {
self == &std::i8::MIN
}
#[inline]
fn get_none() -> i8 {
std::i8::MIN
}
}
impl Noned for i16 {
#[inline]
fn is_none(&self) -> bool {
self == &std::i16::MIN
}
#[inline]
fn get_none() -> i16 {
std::i16::MIN
}
}
impl Noned for i32 {
#[inline]
fn is_none(&self) -> bool {
self == &std::i32::MIN
}
#[inline]
fn get_none() -> i32 {
std::i32::MIN
}
}
impl Noned for i64 {
#[inline]
fn is_none(&self) -> bool {
self == &std::i64::MIN
}
#[inline]
fn get_none() -> i64 {
std::i64::MIN
}
}
impl Noned for isize {
#[inline]
fn is_none(&self) -> bool {
self == &std::isize::MIN
}
#[inline]
fn get_none() -> isize {
std::isize::MIN
}
}
impl Noned for f32 {
#[inline]
fn is_none(&self) -> bool {
self.is_nan()
}
#[inline]
fn get_none() -> f32 {
std::f32::NAN
}
}
impl Noned for f64 {
#[inline]
fn is_none(&self) -> bool {
self.is_nan()
}
#[inline]
fn get_none() -> f64 {
std::f64::NAN
}
}
impl Noned for char {
#[inline]
fn is_none(&self) -> bool { *self == '\0' }
#[inline]
fn get_none() -> char { '\0' }
}
pub trait OptEq {
#[inline]
fn opt_eq(&self, other: &Self) -> bool;
}
impl OptEq for u8 {
fn opt_eq(&self, other: &Self) -> bool {
self == other
}
}
impl OptEq for u16 {
fn opt_eq(&self, other: &Self) -> bool {
self == other
}
}
impl OptEq for u32 {
fn opt_eq(&self, other: &Self) -> bool {
self == other
}
}
impl OptEq for u64 {
fn opt_eq(&self, other: &Self) -> bool {
self == other
}
}
impl OptEq for usize {
fn opt_eq(&self, other: &Self) -> bool {
self == other
}
}
impl OptEq for i8 {
fn opt_eq(&self, other: &Self) -> bool {
self == other
}
}
impl OptEq for i16 {
fn opt_eq(&self, other: &Self) -> bool {
self == other
}
}
impl OptEq for i32 {
fn opt_eq(&self, other: &Self) -> bool {
self == other
}
}
impl OptEq for i64 {
fn opt_eq(&self, other: &Self) -> bool {
self == other
}
}
impl OptEq for isize {
fn opt_eq(&self, other: &Self) -> bool {
self == other
}
}
impl OptEq for f32 {
fn opt_eq(&self, other: &Self) -> bool {
if self.is_nan() {
other.is_nan()
} else {
self == other
}
}
}
impl OptEq for f64 {
fn opt_eq(&self, other: &Self) -> bool {
if self.is_nan() {
other.is_nan()
} else {
self == other
}
}
}
impl OptEq for char {
fn opt_eq(&self, other: &Self) -> bool {
self == other
}
}
pub trait OptOrd {
#[inline]
fn opt_cmp(&self, other: &Self) -> Ordering;
}
#[inline]
fn _opt_cmp<T: Ord + Copy + Noned>(a: &T, b: &T) -> Ordering {
if a.is_none() {
if b.is_none() {
Ordering::Equal
} else {
Ordering::Less
}
} else if b.is_none() {
Ordering::Greater
} else {
a.cmp(b)
}
}
#[inline]
fn _opt_cmp_part<T: PartialOrd + Copy + Noned>(a: &T, b: &T) -> Ordering {
if a.is_none() {
if b.is_none() {
Ordering::Equal
} else {
Ordering::Less
}
} else if b.is_none() {
Ordering::Greater
} else {
a.partial_cmp(b).unwrap()
}
}
impl OptOrd for u8 {
fn opt_cmp(&self, other: &Self) -> Ordering {
_opt_cmp(self, other)
}
}
impl OptOrd for u16 {
fn opt_cmp(&self, other: &Self) -> Ordering {
_opt_cmp(self, other)
}
}
impl OptOrd for u32 {
fn opt_cmp(&self, other: &Self) -> Ordering {
_opt_cmp(self, other)
}
}
impl OptOrd for u64 {
fn opt_cmp(&self, other: &Self) -> Ordering {
_opt_cmp(self, other)
}
}
impl OptOrd for usize {
fn opt_cmp(&self, other: &Self) -> Ordering {
_opt_cmp(self, other)
}
}
impl OptOrd for i8 {
fn opt_cmp(&self, other: &Self) -> Ordering {
self.cmp(other)
}
}
impl OptOrd for i16 {
fn opt_cmp(&self, other: &Self) -> Ordering {
self.cmp(other)
}
}
impl OptOrd for i32 {
fn opt_cmp(&self, other: &Self) -> Ordering {
self.cmp(other)
}
}
impl OptOrd for i64 {
fn opt_cmp(&self, other: &Self) -> Ordering {
self.cmp(other)
}
}
impl OptOrd for isize {
fn opt_cmp(&self, other: &Self) -> Ordering {
self.cmp(other)
}
}
impl OptOrd for f32 {
fn opt_cmp(&self, other: &Self) -> Ordering {
_opt_cmp_part(self, other)
}
}
impl OptOrd for f64 {
fn opt_cmp(&self, other: &Self) -> Ordering {
_opt_cmp_part(self, other)
}
}
impl OptOrd for char {
fn opt_cmp(&self, other: &Self) -> Ordering {
_opt_cmp(self, other)
}
}
#[derive(Copy, Clone)]
pub struct Optioned<T: Noned + Copy> {
value: T,
}
impl<T> PartialEq for Optioned<T>
where
T: OptEq + Noned + Copy,
{
#[inline]
fn eq(&self, other: &Self) -> bool {
self.value.opt_eq(&other.value)
}
}
impl<T> Eq for Optioned<T>
where
T: OptEq + Noned + Copy,
{
}
impl<T> PartialOrd for Optioned<T>
where
T: PartialEq + OptEq + OptOrd + Noned + Copy,
{
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.value.opt_cmp(&other.value))
}
}
impl<T> Ord for Optioned<T>
where
T: Eq + OptEq + OptOrd + Noned + Copy,
{
#[inline]
fn cmp(&self, other: &Self) -> Ordering {
self.value.opt_cmp(&other.value)
}
}
impl<T> Hash for Optioned<T>
where
T: Noned + Copy + Hash,
{
#[inline]
fn hash<H>(&self, state: &mut H)
where
H: Hasher,
{
self.value.hash(state)
}
}
#[cfg(feature = "serde")]
impl<'de, T> serde::Deserialize<'de> for Optioned<T>
where
T: Noned + Copy + serde::Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> Result<Optioned<T>, D::Error>
where
D: serde::Deserializer<'de>,
{
Option::<T>::deserialize(deserializer).map(Optioned::from)
}
}
#[cfg(feature = "serde")]
impl<T> serde::Serialize for Optioned<T>
where
T: Noned + Copy + serde::Serialize,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
let opt = if self.value.is_none() {
Option::None
} else {
Option::Some(self.value)
};
opt.serialize(serializer)
}
}
impl<T: Noned + Copy> Optioned<T> {
#[inline]
pub fn some(t: T) -> Self {
assert!(!t.is_none());
Optioned::<T> { value: t }
}
#[inline]
pub fn none() -> Self {
Optioned::<T> {
value: <T as Noned>::get_none(),
}
}
#[inline]
pub fn into_option(self) -> Option<T> {
if self.value.is_none() {
Option::None
} else {
Option::Some(self.value)
}
}
#[inline]
pub fn is_none(&self) -> bool {
self.value.is_none()
}
#[inline]
pub fn is_some(&self) -> bool {
!self.value.is_none()
}
#[inline]
pub fn expect(&self, msg: &str) -> T {
if self.is_none() {
panic!("{}", msg)
}
self.value
}
#[inline]
pub fn unwrap(&self) -> T {
self.expect("unwrap called on None")
}
#[inline]
pub fn unpack(&self) -> T {
self.value
}
#[inline]
pub fn unwrap_or(&self, def: T) -> T {
if self.is_none() {
def
} else {
self.value
}
}
#[inline]
pub fn unwrap_or_else<F>(self, f: F) -> T
where
F: FnOnce() -> T,
{
if self.is_none() {
f()
} else {
self.value
}
}
#[inline]
pub fn map<U, F>(self, f: F) -> Option<U>
where
F: FnOnce(T) -> U,
{
if self.is_none() {
Option::None
} else {
Option::Some(f(self.value))
}
}
#[inline]
pub fn map_t<U, F>(self, f: F) -> Optioned<U>
where
F: FnOnce(T) -> U,
U: Noned + Copy,
{
if self.is_none() {
none()
} else {
some(f(self.value))
}
}
#[inline]
pub fn map_or<U, F>(self, default: U, f: F) -> U
where
F: FnOnce(T) -> U,
{
if self.is_none() {
default
} else {
f(self.value)
}
}
#[inline]
pub fn map_or_else<U, D, F>(self, default: D, f: F) -> U
where
D: FnOnce() -> U,
F: FnOnce(T) -> U,
{
if self.is_none() {
default()
} else {
f(self.value)
}
}
#[inline]
pub fn or(self, other: Optioned<T>) -> Optioned<T> {
if self.is_some() {
self
} else {
other
}
}
pub fn or_else<F>(self, f: F) -> Optioned<T>
where
F: FnOnce() -> Optioned<T>,
{
if self.is_some() {
self
} else {
f()
}
}
#[inline]
pub fn and<U>(self, other: Optioned<U>) -> Optioned<U>
where
U: Noned + Copy
{
if self.is_some() {
other
} else {
none::<U>()
}
}
#[inline]
pub fn and_then<F,U>(self, f: F) -> Optioned<U>
where
F: FnOnce(T) -> Optioned<U>,
U: Noned + Copy
{
if self.is_some() {
f(self.value)
} else {
none()
}
}
#[inline]
pub fn ok_or<E>(self, err: E) -> Result<T, E> {
if self.is_some(){
Ok(self.value)
} else {
Err(err)
}
}
#[inline]
pub fn ok_or_else<E, F: FnOnce() -> E>(self, err: F) -> Result<T, E> {
if self.is_some(){
Ok(self.value)
} else {
Err(err())
}
}
#[inline]
pub fn take(&mut self) -> Option<T> {
mem::replace(self, Self::none()).into_option()
}
#[inline]
pub fn as_slice(&self) -> &[T] {
&std::slice::from_ref(&self.value)[..self.is_some() as usize]
}
#[inline]
pub fn iter(&self) -> OptionedIter<T> {
OptionedIter { o: *self } }
}
pub fn some<T: Noned + Copy>(value: T) -> Optioned<T> {
Optioned::<T>::some(value)
}
pub fn none<T: Noned + Copy>() -> Optioned<T> {
Optioned::<T>::none()
}
pub fn wrap<T: Noned + Copy>(v: T) -> Optioned<T> {
Optioned { value: v }
}
impl<T: Noned + Copy + Debug> Debug for Optioned<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), Error> {
if self.is_none() {
write!(f, "None")
} else {
write!(f, "Some({:?})", &self.value)
}
}
}
impl<T: Noned + Copy> Default for Optioned<T> {
#[inline]
fn default() -> Optioned<T> {
none()
}
}
#[derive(Copy, Clone)]
pub struct OptionedIter<T: Noned + Copy> {
o: Optioned<T>,
}
impl<T: Noned + Copy> Iterator for OptionedIter<T> {
type Item = T;
#[inline]
fn next(&mut self) -> Option<T> {
self.o.take()
}
}
impl<'a, T: Noned + Copy> From<&'a Option<T>> for Optioned<T> {
#[inline]
fn from(o: &Option<T>) -> Optioned<T> {
o.map_or_else(Self::none, Self::some)
}
}
impl<T: Noned + Copy> From<Option<T>> for Optioned<T> {
#[inline]
fn from(o: Option<T>) -> Optioned<T> {
o.map_or_else(Self::none, Self::some)
}
}
impl<T: Noned + Copy> Into<Option<T>> for Optioned<T> {
#[inline]
fn into(self) -> Option<T> {
self.into_option()
}
}
impl<'a, T: Noned + Copy> Into<Option<T>> for &'a Optioned<T> {
#[inline]
fn into(self) -> Option<T> {
self.into_option()
}
}
impl<T: Noned + Copy> From<T> for Optioned<T> {
#[inline]
fn from(o: T) -> Optioned<T> {
wrap(o)
}
}