#![deny(missing_docs)]
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, 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 PartialEq for OptionBool {
#[inline]
fn eq(&self, other: &OptionBool) -> bool {
match (self, other) {
(&SomeTrue, &SomeTrue) |
(&SomeFalse, &SomeFalse) |
(&None, &None) => true,
_ => false,
}
}
}
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),
}
}
}
const OB_TRUE_SLICE : [bool; 1] = [true];
const OB_FALSE_SLICE : [bool; 1] = [false];
const OB_EMPTY_SLICE : [bool; 0] = [];
const OB_TRUE_SLICE_REF : &'static [bool] = &OB_TRUE_SLICE;
const OB_FALSE_SLICE_REF : &'static [bool] = &OB_FALSE_SLICE;
const OB_EMPTY_SLICE_REF : &'static [bool] = &OB_EMPTY_SLICE;
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 &None = self { false } else { true }
}
#[inline]
pub fn is_none(&self) -> bool {
if let &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 }
}
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 }
}
}
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) }
}
#[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)
}
}
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]
fn as_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 take(&mut self) -> Option<T> {
mem::replace(self, Self::none()).as_option()
}
#[inline]
pub fn as_slice(&self) -> &[T] {
unsafe {
std::slice::from_raw_parts(&self.value,
if self.is_none() { 0 } else { 1 })
}
}
#[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.as_option() }
}