// Copyright 2015 Andre Bogus
// Licensed under the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>. This file may not be copied, modified,
// or distributed except according to those terms.

//! # Space-efficient optional values
//!
//! ## Booleans
//!
//! Type `OptionBool` represents an optional boolean value, similar to
//! `Option<bool>`. Most function implementations are similar or equal.
//! Note that the `map_bool(..)` `and_bool(..)`, `and_then_bool(..)`,
//!`or_bool(..)` and `or_else_bool(..)` functions are working similar to the
//! methods without the `_bool` suffix, but require and return `OptionBool`
//! instead of `Option<bool>`. This allows people to stay within the type.
//!
//! The `OptionBool` type is expected to require only 1 byte of storage:
//!
//! ```rust
//! assert!(1 == std::mem::size_of::<optional::OptionBool>());
//! ```
//! However, since this crate was originally authored, [improvements in the
//! compiler](https://users.rust-lang.org/t/list-of-fundamental-crates/17806/5?u=ryan)
//! have built in this optimization for `Option<bool>` as well. The
//! `OptionBool` type remains however because it [may still perform faster in
//! some bench marks](https://github.com/llogiq/optional/issues/33).
//!
//! ```rust
//! assert!(1 == std::mem::size_of::<Option<bool>>());
//! ```
//!
//! ## Any type can be optional
//!
//! Then there is the `Optioned<T>` type which wraps a type `T` as an optional
//! value of `T` where one particular value represents None. `Optioned<T>`
//! requires the exact same space as T:
//!
//! ```rust
//! assert!(std::mem::size_of::<optional::Optioned<i64>>() ==
//!     std::mem::size_of::<i64>());
//! assert!(std::mem::size_of::<optional::Optioned<f32>>() ==
//!     std::mem::size_of::<f32>());
//! assert!(std::mem::size_of::<optional::Optioned<u8>>() ==
//!     std::mem::size_of::<u8>());
//! ```
//!
//! There are implementations for `u8..64,usize` with `std::u..::MAX`
//! representing None, also for `i8..64,isize` with `std::i..::MIN`
//! representing None, and for `f32, f64` with `std::f..::NAN` representing
//! None.
//!
//! Using Optioned for your own types is as simple as implementing `Noned` for
//! your type, provided that your type is already Copy and Sized.
//!

#![deny(missing_docs)]
#![deny(unsafe_code)]

#[cfg(feature = "serde")]
extern crate serde;

use self::OptionBool::*;
use std::cmp::Ordering;
use std::convert::From;
use std::fmt::{self, Debug, Error};
use std::hash::{Hash, Hasher};
use std::iter::Iterator;
use std::mem;
use std::ops::{Deref, Index, RangeFull};
use std::slice::Iter;

/// The `OptionBool` type, a space-efficient Option<bool> replacement
#[derive(Copy, Clone, PartialEq, Eq, Ord, Hash)]
pub enum OptionBool {
    /// Some(true)
    SomeTrue,
    /// Some(false)
    SomeFalse,
    /// None
    None,
}

// Deref

// we use this for Deref implementation. As they are constant, we obviously
// cannot implement DerefMut.
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;

/// We can deref-coerce to `Option<bool>`
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,
        }
    }
}

/// Index for `RangeFull` (to slice)
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,
        }
    }
}

/// Some(true) > Some(false) > None
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: &[bool] = &OB_TRUE_SLICE;
static OB_FALSE_SLICE_REF: &[bool] = &OB_FALSE_SLICE;
static OB_EMPTY_SLICE_REF: &[bool] = &OB_EMPTY_SLICE;

#[cfg(feature = "serde")]
impl<'de> serde::Deserialize<'de> for OptionBool {
    /// with `feature = "serde"`, (de)serialization support is active.
    ///
    /// ```rust
    ///# extern crate serde_json;
    ///# extern crate optional;
    ///# use optional::OptionBool::SomeTrue;
    ///# fn main() {
    /// assert_eq!("true", serde_json::to_string(&SomeTrue).unwrap());
    ///# }
    /// ```
    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 {
    /// with `feature = "serde"`, (de)serialization support is active.
    ///
    /// ```rust
    ///# extern crate serde_json;
    ///# extern crate optional;
    ///# use optional::OptionBool::SomeTrue;
    ///# fn main() {
    /// assert_eq!(SomeTrue, serde_json::from_str("true").unwrap());
    ///# }
    /// ```
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: serde::Serializer,
    {
        Option::<bool>::from(*self).serialize(serializer)
    }
}

impl OptionBool {
    /// Create a SomeTrue for true, SomeFalse for false
    #[inline]
    pub fn some(b: bool) -> Self {
        if b {
            SomeTrue
        } else {
            SomeFalse
        }
    }

    /// Create a None value.
    ///
    /// # Examples
    ///
    /// ```
    ///# use optional::OptionBool;
    /// assert_eq!(OptionBool::none(), optional::OptionBool::None);
    /// ```
    #[inline]
    pub fn none() -> Self {
        None
    }

    /// Returns true if the option is a Some value.
    ///
    /// # Examples
    ///
    /// ```
    ///# use optional::OptionBool;
    /// assert!(OptionBool::SomeTrue.is_some());
    /// assert!(OptionBool::SomeFalse.is_some());
    /// assert!(!OptionBool::None.is_some());
    /// ```
    #[inline]
    pub fn is_some(self) -> bool {
        if let OptionBool::None = self {
            false
        } else {
            true
        }
    }

    /// Returns true if the option contains the given bool.
    ///
    /// # Example
    ///
    /// ```
    ///# use optional::OptionBool;
    /// assert!(OptionBool::SomeTrue.contains(true));
    /// assert!(!OptionBool::SomeFalse.contains(true));
    /// assert!(!OptionBool::None.contains(false));
    /// ```
    #[inline]
    pub fn contains(self, b: bool) -> bool {
	self == if b { 
            SomeTrue
        } else {
            SomeFalse
        }
    }

    /// Returns true if the option is a Some value.
    ///
    /// # Examples
    ///
    /// ```
    ///# use optional::OptionBool;
    /// assert!(!OptionBool::SomeTrue.is_none());
    /// assert!(!OptionBool::SomeFalse.is_none());
    /// assert!(OptionBool::None.is_none());
    /// ```
    #[inline]
    pub fn is_none(self) -> bool {
        if let OptionBool::None = self {
            true
        } else {
            false
        }
    }

    /// Unwraps the contained bool, panics on None with given message.
    ///
    /// # Panics
    ///
    /// if self is None
    ///
    /// # Examples
    ///
    /// For SomeTrue/SomeFalse, the corresponding bool is returned.
    ///
    /// ```
    ///# use optional::OptionBool;
    /// assert!(OptionBool::SomeTrue.expect("FAIL"));
    /// assert!(!OptionBool::SomeFalse.expect("FAIL"));
    /// ```
    ///
    /// On None, it panics with the given message.
    ///
    /// ```should_panic
    ///# use optional::OptionBool;
    /// OptionBool::None.expect("FAIL"); // panics with FAIL
    /// ```
    #[inline]
    pub fn expect(self, msg: &str) -> bool {
        match self {
            SomeTrue => true,
            SomeFalse => false,
            None => panic!("{}", msg),
        }
    }

    /// Unwraps the contained bool, panics on None.
    ///
    /// # Panics
    ///
    /// if self is None
    ///
    /// # Examples
    ///
    /// For SomeTrue/SomeFalse, the corresponding bool is returned.
    ///
    /// ```
    ///# use optional::OptionBool;
    /// assert!(OptionBool::SomeTrue.unwrap());
    /// assert!(!OptionBool::SomeFalse.unwrap());
    /// ```
    ///
    /// On None, it panics with "unwrap called on None"
    ///
    /// ```should_panic
    ///# use optional::OptionBool;
    /// OptionBool::None.unwrap(); // panics
    /// ```
    #[inline]
    pub fn unwrap(self) -> bool {
        self.expect("unwrap called on None")
    }

    /// Returns the contained bool or a default.
    ///
    /// # Examples
    ///
    /// ```
    ///# use optional::OptionBool;
    /// assert!(OptionBool::SomeTrue.unwrap_or(false));
    /// assert!(!OptionBool::SomeFalse.unwrap_or(true));
    /// assert!(OptionBool::None.unwrap_or(true));
    /// assert!(!OptionBool::None.unwrap_or(false));
    /// ```
    #[inline]
    pub fn unwrap_or(self, def: bool) -> bool {
        match self {
            SomeTrue => true,
            SomeFalse => false,
            None => def,
        }
    }

    /// Returns the contained bool or a computed default.
    ///
    /// # Examples
    ///
    /// ```
    ///# use optional::OptionBool;
    /// assert!(OptionBool::SomeTrue.unwrap_or_else(|| false));
    /// assert!(!OptionBool::SomeFalse.unwrap_or_else(|| panic!()));
    /// assert!(OptionBool::None.unwrap_or_else(|| true));
    /// ```
    #[inline]
    pub fn unwrap_or_else<F>(self, f: F) -> bool
    where
        F: FnOnce() -> bool,
    {
        match self {
            SomeTrue => true,
            SomeFalse => false,
            None => f(),
        }
    }

    /// Maps an `OptionBool` to an `Option<U>` by applying the function
    /// over the contained bool.
    ///
    /// Note that there is also [`map_bool(..)`](#method.map_bool) which works
    /// similarly, but returns another `OptionBool`.
    ///
    /// # Examples
    ///
    /// Convert the contained bool to a Yes/No message
    ///
    /// ```
    ///# use optional::OptionBool;
    /// assert_eq!(Some("Yes"), OptionBool::SomeTrue.map(
    ///     |b| if b { "Yes" } else { "No" }));
    /// ```
    #[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,
        }
    }

    /// Maps an `OptionBool` to another `OptionBool` by applying the
    /// function over the contained bool.
    ///
    /// Note that there is also [`map(..)`](#method.map) which works
    /// similarly, but returns an `Option<bool>`.
    ///
    /// # Examples
    ///
    /// Invert the contained `bool`
    ///
    /// ```
    ///# use optional::OptionBool;
    /// assert_eq!(OptionBool::SomeTrue,
    ///     OptionBool::SomeFalse.map_bool(|b| !b));
    /// ```
    #[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,
        }
    }

    /// Maps a value to a `U` by applying the function or return a
    /// default `U`.
    ///
    /// # Examples
    ///
    /// Map to a string (as per the daily wtf's boolean definition):
    ///
    /// ```
    ///# use optional::OptionBool;
    /// assert_eq!("True", OptionBool::SomeTrue.map_or("FileNotFound",
    ///     |b| if b { "True" } else { "False" }));
    /// ```
    #[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,
        }
    }

    /// Maps a value to a `U` by applying the function or return a
    /// computed default.
    ///
    /// # Examples
    ///
    /// ```
    ///# use optional::OptionBool;
    /// assert_eq!("True", OptionBool::SomeTrue.map_or_else(|| "FileNotFound",
    ///     |b| if b { "True" } else { "False" }));
    /// ```
    #[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(),
        }
    }

    /// Transforms the `OptionBool` into a `Result<bool, E>`, mapping
    /// `Some`X to `Ok(`X`)` and `None` to `Err(err)`.
    ///
    /// # Examples
    ///
    /// ```
    ///# use optional::OptionBool;
    /// assert_eq!(OptionBool::SomeTrue.ok_or("Ouch"), Ok(true));
    /// assert_eq!(OptionBool::None.ok_or("Ouch"), Err("Ouch"));
    /// ```
    #[inline]
    pub fn ok_or<E>(self, err: E) -> Result<bool, E> {
        match self {
            SomeTrue => Ok(true),
            SomeFalse => Ok(false),
            None => Err(err),
        }
    }

    /// Transforms the `OptionBool` into a `Result<bool, E>`, mapping `Some`X to
    /// `Ok(`X`)` and `None` to a calculated `Err(err)`.
    ///
    /// # Examples
    ///
    /// ```
    ///# use optional::OptionBool;
    ///# fn something_expensive() -> bool { unimplemented!(); }
    /// assert_eq!(OptionBool::SomeTrue.ok_or_else(|| something_expensive()), Ok(true));
    /// assert_eq!(OptionBool::None.ok_or_else(|| "Ouch"), Err("Ouch"));
    /// ```
    #[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()),
        }
    }

    /// Returns `None` if the option is `None`, otherwise returns `optb`.
    ///
    /// # Examples
    ///
    /// ```
    ///# use optional::OptionBool;
    /// assert_eq!(Some(1), OptionBool::SomeTrue.and(Some(1)));
    /// assert_eq!(None, OptionBool::None.and(Some(1)));
    /// let actual : Option<u8> = None;
    /// assert_eq!(None, OptionBool::SomeTrue.and(actual));
    /// ```
    #[inline]
    pub fn and<U>(self, optb: Option<U>) -> Option<U> {
        match self {
            SomeTrue | SomeFalse => optb,
            None => Option::None,
        }
    }

    /// Returns `None` if the option is `None`, otherwise returns `optb`.
    ///
    /// # Examples
    ///
    /// ```
    ///# use optional::OptionBool;
    /// assert_eq!(OptionBool::SomeTrue,
    ///     OptionBool::SomeFalse.and_bool(OptionBool::SomeTrue));
    /// assert_eq!(OptionBool::None,
    ///     OptionBool::None.and_bool(OptionBool::SomeFalse));
    /// assert_eq!(OptionBool::None,
    ///     OptionBool::SomeTrue.and_bool(OptionBool::None));
    /// ```
    #[inline]
    pub fn and_bool(self, optb: OptionBool) -> OptionBool {
        match self {
            None => None,
            _ => optb,
        }
    }

    /// returns `None` if the `OptionBool` is `None`, otherwise calls `f` with
    /// the boolean value and returns the result as an `Option<U>`
    ///
    /// Note that there is also [`and_then_bool(..)`](#method.and_then_bool)
    /// which works similarly, but returns another `OptionBool`.
    ///
    /// # Examples
    ///
    /// ```
    ///# use optional::OptionBool;
    /// assert_eq!(None, OptionBool::SomeFalse.and_then(
    ///     |x| if x { Some(true) } else { None }));
    /// ```
    #[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,
        }
    }

    /// returns `None` if the `OptionBool` is `None`, otherwise calls `f` with
    /// the boolean value and returns the result as an `OptionBool`
    ///
    /// Note that there is also [`and_then(..)`](#method.and_then) which works
    /// similarly, but returns an `Option<bool>`.
    ///
    /// # Examples
    ///
    /// ```
    ///# use optional::OptionBool;
    /// assert_eq!(OptionBool::None, OptionBool::SomeFalse.and_then_bool(
    ///     |x| if x { OptionBool::SomeTrue } else { OptionBool::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,
        }
    }

    /// Returns `None` if the `OptionBool` is `None`, otherwise calls
    /// `predicate` with the wrapped value and returns:
    ///
    /// * `SomeTrue` or `SomeFalse` if the predicate returns `true`
    /// * `None` if the predicate returns `false`.
    ///
    /// This function is similar to `Iterator::filter`. You can imagine
    /// `OptionBool` being an iterator over one or zero elements. `filter()`
    /// lets you decide which elements to keep.
    ///
    /// # Examples
    ///
    /// ```
    ///# use optional::OptionBool;
    /// assert!(OptionBool::SomeTrue.filter(|a| !a).is_none());
    /// assert_eq!(OptionBool::SomeFalse.filter(|_| true),
    ///            OptionBool::SomeFalse);
    /// assert!(OptionBool::None.filter(|_| unreachable!()).is_none());
    /// ```
    #[inline]
    pub fn filter<P>(self, predicate: P) -> OptionBool
    where
        P: FnOnce(bool) -> bool,
    {
        match self {
            SomeTrue => {
                if predicate(true) {
                    return SomeTrue;
                }
            }
            SomeFalse => {
                if predicate(false) {
                    return SomeFalse;
                }
            }
            None => {}
        }
        None
    }

    /// Returns this as Option unless this is `None`, in which case returns
    /// `optb`.
    ///
    /// # Examples
    ///
    /// ```
    ///# use optional::OptionBool;
    /// assert_eq!(Some(false), OptionBool::SomeFalse.or(Some(true)));
    /// assert_eq!(Some(true), OptionBool::None.or(Some(true)));
    /// assert_eq!(None, OptionBool::None.or(None));
    /// ```
    #[inline]
    pub fn or(self, optb: Option<bool>) -> Option<bool> {
        match self {
            SomeTrue => Some(true),
            SomeFalse => Some(false),
            None => optb,
        }
    }

    /// Returns this as Option unless this is `None`, in which case returns
    /// `optb`.
    ///
    /// # Examples
    ///
    /// ```
    ///# use optional::OptionBool;
    /// assert_eq!(OptionBool::SomeFalse,
    ///     OptionBool::SomeFalse.or_bool(OptionBool::SomeTrue));
    /// assert_eq!(OptionBool::SomeTrue,
    ///     OptionBool::None.or_bool(OptionBool::SomeTrue));
    /// assert_eq!(OptionBool::None,
    ///     OptionBool::None.or_bool(OptionBool::None));
    /// ```
    #[inline]
    pub fn or_bool(self, optb: OptionBool) -> OptionBool {
        match self {
            None => optb,
            x => x,
        }
    }

    /// Returns this as Option unless this is `None`, in which case use the
    /// supplied function to calculate the result.
    ///
    /// Note that there is also [`or_else_bool(..)`](#method.or_else_bool)
    /// which works similarly, but returns another `OptionBool`.
    ///
    /// # Examples
    ///
    /// ```
    ///# use optional::OptionBool;
    /// assert_eq!(Some(false), OptionBool::SomeFalse.or_else(|| Some(true)));
    /// assert_eq!(Some(true), OptionBool::None.or_else(|| Some(true)));
    /// assert_eq!(None, OptionBool::None.or_else(|| None));
    /// ```
    #[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(),
        }
    }

    /// Returns this as Option unless this is `None`, in which case use the
    /// supplied function to calculate the result.
    ///
    /// Note that there is also [`or_else(..)`](#method.or_else) which works
    /// similarly, but returns an `Option<bool>`.
    ///
    /// # Examples
    ///
    /// ```
    ///# use optional::OptionBool;
    /// assert_eq!(OptionBool::SomeFalse,
    ///     OptionBool::SomeFalse.or_else_bool(|| OptionBool::SomeTrue));
    /// assert_eq!(OptionBool::SomeTrue,
    ///     OptionBool::None.or_else_bool(|| OptionBool::SomeTrue));
    /// assert_eq!(OptionBool::None,
    ///     OptionBool::None.or_else_bool(|| OptionBool::None));
    /// ```
    #[inline]
    pub fn or_else_bool<F>(self, f: F) -> OptionBool
    where
        F: FnOnce() -> OptionBool,
    {
        match self {
            None => f(),
            x => x,
        }
    }

    /// Returns `Some*` if exactly one of self, optb is `Some*`, otherwise
    /// returns None.
    ///
    /// # Examples
    ///
    /// ```
    ///# use optional::OptionBool;
    /// assert!(OptionBool::None.xor(OptionBool::None).is_none());
    /// assert_eq!(OptionBool::SomeTrue.xor(OptionBool::None),
    ///            OptionBool::SomeTrue);
    /// assert_eq!(OptionBool::None.xor(OptionBool::SomeFalse),
    ///            OptionBool::SomeFalse);
    /// assert!(OptionBool::SomeTrue.xor(OptionBool::SomeTrue).is_none())
    /// ```
    pub fn xor(self, optb: OptionBool) -> OptionBool {
        if self.is_none() {
            return optb;
        } else if optb.is_none() {
            return self;
        }
        None
    }

    /// return an iterator over all contained (that is zero or one) values.
    ///
    /// # Examples
    ///
    /// ```
    ///# use optional::OptionBool;
    /// assert_eq!(None, OptionBool::None.iter().next());
    /// assert_eq!(Some(&true), OptionBool::SomeTrue.iter().next());
    /// ```
    #[inline]
    pub fn iter(&self) -> Iter<bool> {
        self.as_slice().iter()
    }

    /// return a possibly empty slice with the contained value, if any.
    ///
    /// # Examples
    ///
    /// ```
    ///# use optional::OptionBool;
    /// assert_eq!(&[true], OptionBool::SomeTrue.as_slice());
    /// assert!(OptionBool::None.as_slice().is_empty());
    /// ```
    #[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,
        }
    }

    /// Takes the value out of the `OptionBool` and returns ist as
    /// `Option<bool>`, changing self to `None`.
    ///
    /// Note that there is also [`take_bool(..)`](#method.take_bool) which
    /// works similarly, but returns an `OptionBool`.
    ///
    /// # Examples
    ///
    /// ```
    ///# use optional::OptionBool;
    /// let mut x = OptionBool::some(true);
    /// assert_eq!(Some(true), x.take());
    /// assert_eq!(OptionBool::None, x);
    /// ```
    #[inline]
    pub fn take(&mut self) -> Option<bool> {
        self.take_bool().into()
    }

    /// Takes the value out of the `OptionBool`, changing self to `None`.
    ///
    /// Note that there is also [`take(..)`](#method.take) which works
    /// similarly, but returns an `Option<bool>`.
    ///
    /// # Examples
    ///
    /// ```
    ///# use optional::OptionBool;
    /// let mut x = OptionBool::some(true);
    /// assert_eq!(OptionBool::some(true), x.take_bool());
    /// assert_eq!(OptionBool::None, x);
    /// ```
    #[inline]
    pub fn take_bool(&mut self) -> OptionBool {
        mem::replace(self, None)
    }

    /// Replaces the actual value in the option by the value given in
    /// parameter, returning the old value if present, leaving a
    /// `Some`{`True`, `False`} in its place.
    ///
    /// # Examples
    ///
    /// ```
    ///# use optional::OptionBool;
    /// let mut x = OptionBool::None;
    /// assert_eq!(OptionBool::None, x.replace(true));
    /// assert_eq!(OptionBool::SomeTrue, x);
    /// ```
    pub fn replace(&mut self, value: bool) -> OptionBool {
        mem::replace(self, if value {
            SomeTrue
        } else {
            SomeFalse
        })
    }
}

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",
            }
        )
    }
}

///iterate over an `OptionBool`
pub struct IterBool {
    o: OptionBool,
}

impl Iterator for IterBool {
    type Item = bool;

    #[inline]
    fn next(&mut self) -> Option<bool> {
        self.o.take()
    }
}

/// `IntoIterator` works as expected
///
/// # Examples
///
/// ```
///# use optional::OptionBool;
/// let mut pass : bool = false;
/// for b in OptionBool::SomeTrue { pass = b; }
/// assert!(pass);
///
/// for b in OptionBool::None { assert!(false); }
/// ```
impl IntoIterator for OptionBool {
    type Item = bool;
    type IntoIter = IterBool;

    #[inline]
    fn into_iter(self) -> IterBool {
        IterBool { o: self }
    }
}

/// `OptionBool` defaults to `None`.
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,
        }
    }
}

/// A trait whose implementation for any type `T` allows the use of
///`Optioned<T>` where `T` is bound by both `Sized` and `Copy`.
pub trait Noned {
    /// Returns `true` if the contained value is the declared `None` for `T`,
    /// `false` otherwise.
    fn is_none(&self) -> bool;
    /// Returns the declared `None` value for `T`.
    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'
    }
}

///Equality within Optioned
pub trait OptEq {
    /// Is the other optioned equal to this one?
    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
    }
}

///Ordering within Optioned
pub trait OptOrd {
    /// compare this Optioned with another
    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)
    }
}

/// An `Option<T>`-like structure that takes only as much space as the enclosed
/// value, at the cost of removing one particular `None` value from the value
/// domain (see `Noned`)
#[derive(Copy, Clone)]
pub struct Optioned<T: Noned + Copy> {
    value: T,
}

/// Equality works as usual.
///
/// # Examples
///
/// ```
///# use ::optional::{some, none};
/// assert_eq!(some(1u8), some(1u8));
/// assert_eq!(none::<u32>(), none::<u32>());
/// ```
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>,
{
    /// with `feature = "serde"`, (de)serialization support is active.
    ///
    /// ```rust
    ///# extern crate serde_json;
    ///# extern crate optional;
    ///# use optional::{Optioned, Noned, some};
    ///# fn main() {
    /// assert_eq!("1.0", serde_json::to_string(&some(1f32)).unwrap());
    ///# }
    /// ```
    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,
{
    /// with `feature = "serde"`, (de)serialization support is active.
    ///
    /// ```rust
    ///# extern crate serde_json;
    ///# extern crate optional;
    ///# use optional::{Optioned, Noned, some};
    ///# fn main() {
    /// assert_eq!(some(1f32), serde_json::from_str("1.0").unwrap());
    ///# }
    /// ```
    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> {
    /// Create an `Optioned<T>` that is `some(t)`.
    ///
    /// # Panics
    ///
    /// panics if the supplied value is the None value
    ///
    /// # Examples
    ///
    /// ```
    ///# use ::optional::Optioned;
    /// Optioned::<i32>::some(1); // Optioned(1)
    /// ```
    ///
    /// ```should_panic
    ///# use ::optional::Optioned;
    /// Optioned::<f64>::some(std::f64::NAN); // panic!s
    /// ```
    #[inline]
    pub fn some(t: T) -> Self {
        assert!(!t.is_none());
        Optioned::<T> { value: t }
    }

    /// Create an `Optioned<T>` that is `none()`.
    ///
    /// # Examples
    ///
    /// ```
    ///# use ::optional::Optioned;
    /// Optioned::<u16>::none(); // Optioned(std::u16::MAX)
    /// ```
    #[inline]
    pub fn none() -> Self {
        Optioned::<T> {
            value: <T as Noned>::get_none(),
        }
    }

    /// Convenience funtion to convert an `Optioned` into an `Option`.
    ///
    /// Techinically this is possible with the `Into<Option<T>>` implementation in this crate.
    /// However, experience has shown that there are many cases where the compiler isn't able to
    /// infer the correct type for the generic parameter and issues an error. As a workaround you
    /// can use `Into::<Option<T>>::into(...)` or `.map(|inner| inner)` which will both work.
    /// The first is verbose and the second makes the intention less clear, so this method is
    /// provided as a convenience.
    ///
    /// ```rust
    ///# use optional::some;
    /// if let Some(val) = some(15).into_option() {
    ///     println!("val = {}", val);
    /// }
    /// ```
    ///
    /// The following example will fail to compile because of type inference.
    /// ```compile_fail
    /// # use optional::some;
    /// if let Some(val) = some(15).into() {
    ///     println!("val = {}", val);
    /// }
    /// ```
    #[inline]
    pub fn into_option(self) -> Option<T> {
        if self.value.is_none() {
            Option::None
        } else {
            Option::Some(self.value)
        }
    }

    /// Returns `true` if this `Optioned` is `None`, `false` otherwise.
    #[inline]
    pub fn is_none(&self) -> bool {
        self.value.is_none()
    }

    /// Returns `true` if this `Optioned` contains a value, `false` otherwise.
    #[inline]
    pub fn is_some(&self) -> bool {
        !self.value.is_none()
    }

    /// Unwraps the value, if any, else panics with the given message.
    ///
    /// # Panics
    ///
    /// if self is None
    ///
    /// # Examples
    ///
    /// For Some(_), the corresponding value is returned.
    ///
    /// ```
    ///# use optional::Optioned;
    /// assert_eq!(42u8, Optioned::some(42u8).expect("FAIL"));
    /// ```
    ///
    /// On None, it panics with the given message.
    ///
    /// ```should_panic
    ///# use optional::Optioned;
    ///Optioned::<u8>::none().expect("FAIL"); // panics with FAIL
    /// ```
    #[inline]
    pub fn expect(&self, msg: &str) -> T {
        if self.is_none() {
            panic!("{}", msg)
        }
        self.value
    }

    /// Unwraps the value, if any, else panics with "unwrap called on None".
    ///
    /// # Panics
    ///
    /// if self is `None`
    ///
    /// # Examples
    ///
    /// For `Some(_)`, the corresponding value is returned.
    ///
    /// ```
    ///# use optional::Optioned;
    /// assert_eq!(42u8, Optioned::some(42u8).unwrap());
    /// ```
    ///
    /// On `None`, it panics with the given message.
    ///
    /// ```should_panic
    ///# use optional::Optioned;
    ///Optioned::<u8>::none().unwrap(); // panics
    /// ```
    #[inline]
    pub fn unwrap(&self) -> T {
        self.expect("unwrap called on None")
    }

    /// Returns the contained value, even if None.
    ///
    /// # Examples
    ///
    /// ```
    ///# use optional::{some, none};
    /// assert_eq!(-128i8, none().unpack());
    /// assert_eq!(1u32, some(1).unpack());
    /// ```
    #[inline]
    pub fn unpack(&self) -> T {
        self.value
    }

    /// Returns the contained value or a default.
    ///
    /// # Examples
    ///
    /// ```
    ///# use optional::{some, none};
    /// assert_eq!(-1i8, some(-1i8).unwrap_or(127i8));
    /// assert_eq!(42u16, none().unwrap_or(42u16));
    /// ```
    #[inline]
    pub fn unwrap_or(&self, def: T) -> T {
        if self.is_none() {
            def
        } else {
            self.value
        }
    }

    /// Returns the contained value or a calculated default.
    ///
    /// # Examples
    ///
    /// ```
    ///# use optional::{some, none};
    /// assert_eq!(-1i8, some(-1i8).unwrap_or_else(|| panic!()));
    /// assert_eq!(42u16, none().unwrap_or_else(|| 42u16));
    /// ```
    #[inline]
    pub fn unwrap_or_else<F>(self, f: F) -> T
    where
        F: FnOnce() -> T,
    {
        if self.is_none() {
            f()
        } else {
            self.value
        }
    }

    /// Maps the `Optioned` to an `Option<U>` by applying the function over the
    /// contained value, if any.
    ///
    /// # Examples
    /// ```
    ///# use optional::{some, none};
    /// assert_eq!(Some(-42), some(42i8).map(|x| -x));
    /// assert_eq!(None, none::<i8>().map(|x| -x));
    /// ```
    #[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))
        }
    }

    /// Maps the `Optioned<T>` to an `Optioned<U>` by applying the function over
    /// the contained value, if any. Requires that the result type of the
    /// function be `Noned + Copy`, as other types aren't compatible with
    /// Optioned.
    ///
    /// # Examples
    /// ```
    ///# use optional::{some, none};
    /// assert_eq!(some(-42), some(42i8).map_t(|x| -x));
    /// assert_eq!(none::<i8>(), none::<i8>().map_t(|x| -x));
    /// ```
    #[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))
        }
    }

    /// Maps the contained value to a `U` by applying the function or return a
    /// default.
    ///
    /// # Examples
    /// ```
    ///# use optional::{some, none};
    /// assert_eq!("1", some(1usize).map_or("Unknown".to_string(), |b| b.to_string()));
    /// assert_eq!("Unknown", none::<usize>().map_or("Unknown".to_string(), |b| b.to_string()));
    /// ```
    #[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)
        }
    }

    /// Maps a value to a `U` by applying the function or return a computed
    /// default.
    ///
    /// # Examples
    /// ```
    ///# use optional::{some, none};
    /// assert_eq!("1", some(1usize).map_or_else(|| "Unknown".to_string(),
    ///     |b| b.to_string()));
    /// assert_eq!("Unknown", none::<usize>().map_or_else(
    ///     || "Unknown".to_string(), |b| b.to_string()));
    /// ```
    #[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)
        }
    }

    /// Returns this option if it contains a value, otherwise returns the other.
    ///
    /// Arguments passed to `or` are eagerly evaluated;
    /// if you are passing the result of a function call,
    /// it is recommended to use `or_else`, which is lazily evaluated.
    ///
    /// # Examples
    ///
    /// ```
    /// # use optional::{Optioned, some, none};
    /// let x = some(2);
    /// let y = none();
    /// assert_eq!(x.or(y), some(2));
    ///
    /// let x = none();
    /// let y = some(100);
    /// assert_eq!(x.or(y), some(100));
    ///
    /// let x = some(2);
    /// let y = some(100);
    /// assert_eq!(x.or(y), some(2));
    ///
    /// let x: Optioned<u32> = none();
    /// let y = none();
    /// assert_eq!(x.or(y), none());
    /// ```
    #[inline]
    pub fn or(self, other: Optioned<T>) -> Optioned<T> {
        if self.is_some() {
            self
        } else {
            other
        }
    }

    /// Returns this option if it contains a value, otherwise calls `f` and returns the result.
    ///
    /// # Examples
    ///
    /// ```
    /// # use optional::{Optioned, some, none};
    /// fn nothing() -> Optioned<u32> { none() }
    /// fn something() -> Optioned<u32> { some(1) }
    ///
    /// assert_eq!(some(2).or_else(something), some(2));
    /// assert_eq!(none().or_else(something), some(1));
    /// assert_eq!(none().or_else(nothing), none());
    /// ```
    pub fn or_else<F>(self, f: F) -> Optioned<T>
    where
        F: FnOnce() -> Optioned<T>,
    {
        if self.is_some() {
            self
        } else {
            f()
        }
    }

    /// Returns `Some*` if exactly one of self, optb is `Some*`, otherwise
    /// returns None.
    ///
    /// # Examples
    ///
    /// ```
    ///# use optional::{Optioned, none, some};
    /// assert!(none::<u8>().xor(none()).is_none());
    /// assert_eq!(some(42u8).xor(none()), some(42));
    /// assert_eq!(none().xor(some(0u16)), some(0));
    /// assert!(some(99u32).xor(some(99u32)).is_none());
    /// ```
    pub fn xor(self, optb: Self) -> Self {
        if self.is_none() {
            return optb;
        } else if optb.is_none() {
            return self;
        }
        none()
    }

    /// Returns the `None` value for type `U` if this value or `other` contains their respective
    /// `None` values. Otherwise returns the `other` `Optioned` struct.
    ///
    /// # Examples
    ///
    /// ```
    /// # use optional::{Optioned, some, none};
    /// let the_other = some::<u32>(42);
    ///
    /// assert_eq!(some('a').and(the_other), some(42));
    /// assert_eq!(none::<char>().and(the_other), none::<u32>());
    /// assert_eq!(some('a').and(none::<u32>()), none::<u32>());
    /// assert_eq!(none::<char>().and(none::<u32>()), none::<u32>());
    /// ```
    #[inline]
    pub fn and<U>(self, other: Optioned<U>) -> Optioned<U>
    where
        U: Noned + Copy,
    {
        if self.is_some() {
            other
        } else {
            none::<U>()
        }
    }

    /// Returns this `Optioned` if it contains the the `None` value, otherwise calls `f` with
    /// the contained value and returns the result as an `Optioned<U>`.
    ///
    /// # Examples
    ///
    /// ```
    /// # use optional::{Optioned, some, none, wrap};
    /// fn nothing() -> Optioned<u32> { none() }
    /// fn something() -> Optioned<u32> { some(1) }
    /// fn add_two(val: u32) -> Optioned<u32> {
    ///   wrap( val + 2)
    /// }
    ///
    /// fn failed_function(val: u32) -> Optioned<u32> {
    ///   none()
    /// }
    ///
    /// assert_eq!(some(2).and_then(add_two), some(4));
    /// assert_eq!(none().and_then(add_two), none());
    /// assert_eq!(some(2).and_then(failed_function), none());
    /// assert_eq!(none().and_then(failed_function), none());
    /// ```
    #[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()
        }
    }

    /// Returns `None` if the `Optioned` is none, otherwise calls
    /// `predicate` with the wrapped value and returns:
    ///
    /// * `Some(value)` if the predicate returns `true`
    /// * `None` if the predicate returns `false`.
    ///
    /// This function is similar to `Iterator::filter`. You can imagine
    /// `Optioned` being an iterator over one or zero elements. `filter()`
    /// lets you decide which elements to keep.
    ///
    /// # Examples
    ///
    /// ```
    ///# use optional::{Optioned, some, none};
    /// assert!(some(42u8).filter(|a| a > 99).is_none());
    /// assert_eq!(some(42u16).filter(|_| true),
    ///            some(42));
    /// assert!(none().filter(|_: u32| unreachable!()).is_none());
    /// ```
    #[inline]
    pub fn filter<P>(self, predicate: P) -> Self
    where
        P: FnOnce(T) -> bool,
    {
        if self.is_some() && predicate(self.value) {
            self
        } else {
            none()
        }
    }

    /// Transforms the `Optioned<T>` into a `Result<T, E>`, mapping `some(v)` to
    /// `Ok(v)` and `none()` to `Err(err)`.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use optional::{Optioned, some, none};
    ///
    /// let x = some(42u32);
    /// assert_eq!(x.ok_or("was none"), Ok(42u32));
    ///
    /// let x: Optioned<u32> = none();
    /// assert_eq!(x.ok_or("was none"), Err("was none"));
    /// ```
    #[inline]
    pub fn ok_or<E>(self, err: E) -> Result<T, E> {
        if self.is_some() {
            Ok(self.value)
        } else {
            Err(err)
        }
    }

    /// Transforms the `Optioned<T>` into a `Result<T, E>`, mapping `some(v)` to
    /// `Ok(v)` and `none()` to `Err(err)`.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use optional::{Optioned, some, none};
    ///
    /// let x = some(42u32);
    /// assert_eq!(x.ok_or_else(|| "was none"), Ok(42u32));
    ///
    /// let x: Optioned<u32> = none();
    /// assert_eq!(x.ok_or_else(|| "was none"), Err("was none"));
    /// ```
    #[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())
        }
    }

    /// Takes the value out of the `Optioned` and returns ist as
    /// `Option<T>`, changing self to `None`.
    ///
    /// # Examples
    ///
    /// ```
    ///# use optional::{some, none};
    /// let mut x = some(1u8);
    /// assert_eq!(Some(1u8), x.take());
    /// assert!(x.is_none());
    /// ```
    #[inline]
    pub fn take(&mut self) -> Option<T> {
        mem::replace(self, Self::none()).into_option()
    }

    /// Return a possibly empty slice over the contained value, if any.
    ///
    /// # Examples
    /// ```
    ///# use optional::{some, none};
    /// assert_eq!(&[42], some(42u8).as_slice());
    /// assert!(none::<i16>().as_slice().is_empty());
    /// ```
    #[inline]
    pub fn as_slice(&self) -> &[T] {
        &std::slice::from_ref(&self.value)[..self.is_some() as usize]
    }

    /// return an iterator over all contained (that is zero or one) values.
    ///
    /// # Examples
    ///
    /// ```
    ///# use optional::{some, none};
    /// assert_eq!(None, none::<u64>().iter().next());
    /// assert_eq!(Some(42u64), some(42u64).iter().next());
    /// ```
    #[inline]
    pub fn iter(&self) -> OptionedIter<T> {
        OptionedIter { o: *self } // make a copy
    }

    /// Replaces the actual value in the option by the value given in
    /// parameter, returning the old value if present, leaving a
    /// `Some`{`True`, `False`} in its place.
    ///
    /// # Examples
    ///
    /// ```
    ///# use optional::{some, none};
    /// let mut x = none();
    /// assert_eq!(none(), x.replace(1_u32));
    /// assert_eq!(some(1u32), x);
    /// ```
    pub fn replace(&mut self, value: T) -> Self {
        mem::replace(self, some(value))
    }
}

impl<T: Noned + Copy + PartialEq> Optioned<T> {
    /// Returns `true' if this `Optioned` contains the given value,
    /// `false` otherwise.
    ///
    /// # Examples
    ///
    /// ```
    ///# use optional::{some, none};
    /// assert!(some(42u8).contains(42));
    /// assert!(!some(1u32).contains(12));
    /// assert!(!none().contains(0usize));
    /// ```
    #[inline]
    pub fn contains(&self, value: T) -> bool {
        self.is_some() && self.value == value
    }
}

/// Create an `Optioned<T>` that is `some(t)`.
///
/// # Panics
///
/// panics if the supplied value is the None value
///
/// # Examples
///
/// ```
///# use ::optional::some;
/// some(1i32); // Optioned(1i32)
/// ```
///
/// ```should_panic
///# use ::optional::some;
/// some(std::f64::NAN); // panic!s
/// ```
pub fn some<T: Noned + Copy>(value: T) -> Optioned<T> {
    Optioned::<T>::some(value)
}

/// Create a `None Optioned<T>`. Note that the type must be inferrible
/// from the context, or you'd need to call with `::<T>` where `T` is
/// the specific type.
///
/// # Examples
///
/// ```
///# use ::optional::{none, Optioned};
/// let x : Optioned<i16> = none();
/// none::<f32>();
/// ```
pub fn none<T: Noned + Copy>() -> Optioned<T> {
    Optioned::<T>::none()
}

/// Wrap a `T` into an `Optioned<T>`, regardless of its None-ness.
///
/// # Examples
///
/// ```
///# use optional::wrap;
/// assert!(wrap(1u8).is_some());
/// assert!(wrap(255u8).is_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()
    }
}

/// iterate over an Optioned<T>
#[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)
    }
}
