preserves 4.996.0

Implementation of the Preserves serialization format via serde.
Documentation
//! Representation of Preserves `SignedInteger`s as [i128]/[u128] (if they fit) or [BigInt] (if
//! they don't).

use num::bigint::BigInt;
use num::traits::cast::ToPrimitive;
use num::traits::sign::Signed;
use std::borrow::Cow;
use std::cmp::{Ord, Ordering, PartialOrd};
use std::convert::TryFrom;
use std::convert::TryInto;
use std::fmt;

/// Internal representation of Preserves `SignedInteger`s.
///
/// Invariant: if I128 can be used, it will be; otherwise, if U128 can be used, it will be;
/// otherwise, Big will be used.
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub enum SignedIntegerRepr {
    I128(i128),
    U128(u128),
    Big(Box<BigInt>),
}

/// Main representation of Preserves `SignedInteger`s.
#[derive(Clone, PartialEq, Eq, Hash)]
pub struct SignedInteger(SignedIntegerRepr);

impl fmt::Debug for SignedInteger {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "{}n", self)
    }
}

impl fmt::Display for SignedInteger {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match self.repr() {
            SignedIntegerRepr::I128(i) => i.fmt(f),
            SignedIntegerRepr::U128(u) => u.fmt(f),
            SignedIntegerRepr::Big(n) => n.fmt(f),
        }
    }
}

impl Ord for SignedInteger {
    fn cmp(&self, other: &Self) -> Ordering {
        match self.repr() {
            SignedIntegerRepr::I128(i1) => match other.repr() {
                SignedIntegerRepr::I128(i2) => i1.cmp(i2),
                SignedIntegerRepr::U128(_) => {
                    if *i1 < 0 {
                        Ordering::Less
                    } else {
                        Ordering::Greater
                    }
                }
                SignedIntegerRepr::Big(n) => {
                    if n.is_negative() {
                        Ordering::Less
                    } else {
                        Ordering::Greater
                    }
                }
            },
            SignedIntegerRepr::U128(u1) => match other.repr() {
                SignedIntegerRepr::I128(_) => Ordering::Greater,
                SignedIntegerRepr::U128(u2) => u1.cmp(u2),
                SignedIntegerRepr::Big(n) => {
                    if n.is_positive() {
                        Ordering::Less
                    } else {
                        Ordering::Greater
                    }
                }
            },
            SignedIntegerRepr::Big(n1) => match other.repr() {
                SignedIntegerRepr::I128(_) | SignedIntegerRepr::U128(_) => {
                    if n1.is_negative() {
                        Ordering::Less
                    } else {
                        Ordering::Greater
                    }
                }
                SignedIntegerRepr::Big(n2) => n1.cmp(n2),
            },
        }
    }
}

impl PartialOrd for SignedInteger {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl SignedInteger {
    /// Extract the internal representation.
    pub fn repr(&self) -> &SignedIntegerRepr {
        &self.0
    }

    /// Does this `SignedInteger` fit in an [i128]? (See also [the TryFrom instance for
    /// i128](#impl-TryFrom<%26SignedInteger>-for-i128).)
    pub fn is_i(&self) -> bool {
        matches!(self.0, SignedIntegerRepr::I128(_))
    }

    /// Does this `SignedInteger` fit in a [u128], but not an [i128]? (See also [the TryFrom
    /// instance for u128](#impl-TryFrom<%26SignedInteger>-for-u128).)
    pub fn is_u(&self) -> bool {
        matches!(self.0, SignedIntegerRepr::U128(_))
    }

    /// Does this `SignedInteger` fit neither in a [u128] nor an [i128]? (See also [the TryFrom
    /// instance for BigInt](#impl-From<%26'a+SignedInteger>-for-BigInt).)
    pub fn is_big(&self) -> bool {
        matches!(self.0, SignedIntegerRepr::Big(_))
    }
}

//--

macro_rules! map_integral_type_to_signed_integer {
    ($iN:ident, $uN:ident) => {
        impl From<$iN> for SignedInteger {
            fn from(v: $iN) -> Self {
                SignedInteger(SignedIntegerRepr::I128(v.into()))
            }
        }

        impl From<$uN> for SignedInteger {
            fn from(v: $uN) -> Self {
                SignedInteger(SignedIntegerRepr::I128(v.into()))
            }
        }

        impl TryFrom<&SignedInteger> for $iN {
            type Error = ();
            fn try_from(v: &SignedInteger) -> Result<Self, Self::Error> {
                i128::try_from(v)?.try_into().map_err(|_| ())
            }
        }

        impl TryFrom<&SignedInteger> for $uN {
            type Error = ();
            fn try_from(v: &SignedInteger) -> Result<Self, Self::Error> {
                u128::try_from(v)?.try_into().map_err(|_| ())
            }
        }
    };
}

map_integral_type_to_signed_integer!(i8, u8);
map_integral_type_to_signed_integer!(i16, u16);
map_integral_type_to_signed_integer!(i32, u32);
map_integral_type_to_signed_integer!(i64, u64);

//--

impl From<i128> for SignedInteger {
    fn from(v: i128) -> Self {
        SignedInteger(SignedIntegerRepr::I128(v))
    }
}

impl From<u128> for SignedInteger {
    fn from(v: u128) -> Self {
        if let Ok(w) = v.try_into() {
            SignedInteger(SignedIntegerRepr::I128(w))
        } else {
            SignedInteger(SignedIntegerRepr::U128(v))
        }
    }
}

impl TryFrom<&SignedInteger> for i128 {
    type Error = ();
    fn try_from(v: &SignedInteger) -> Result<Self, Self::Error> {
        match v.repr() {
            SignedIntegerRepr::I128(i) => Ok(*i),
            SignedIntegerRepr::U128(_) => Err(()),
            SignedIntegerRepr::Big(_) => Err(()),
        }
    }
}

impl TryFrom<&SignedInteger> for u128 {
    type Error = ();
    fn try_from(v: &SignedInteger) -> Result<Self, Self::Error> {
        match v.repr() {
            SignedIntegerRepr::I128(i) => i.to_u128().ok_or(()),
            SignedIntegerRepr::U128(u) => Ok(*u),
            SignedIntegerRepr::Big(_) => Err(()),
        }
    }
}

//--

impl From<BigInt> for SignedInteger {
    fn from(v: BigInt) -> Self {
        Self::from(Cow::Owned(v))
    }
}

impl<'a> From<&'a SignedInteger> for BigInt {
    fn from(v: &'a SignedInteger) -> Self {
        match v.repr() {
            SignedIntegerRepr::I128(i) => BigInt::from(*i),
            SignedIntegerRepr::U128(u) => BigInt::from(*u),
            SignedIntegerRepr::Big(n) => *n.clone(),
        }
    }
}

//--

impl<'a> From<Cow<'a, BigInt>> for SignedInteger {
    fn from(v: Cow<'a, BigInt>) -> Self {
        if let Some(w) = v.to_i128() {
            SignedInteger(SignedIntegerRepr::I128(w))
        } else if let Some(w) = v.to_u128() {
            SignedInteger(SignedIntegerRepr::U128(w))
        } else {
            SignedInteger(SignedIntegerRepr::Big(Box::new(v.into_owned())))
        }
    }
}

impl<'a> From<&'a SignedInteger> for Cow<'a, BigInt> {
    fn from(v: &'a SignedInteger) -> Self {
        match v.repr() {
            SignedIntegerRepr::I128(i) => Cow::Owned(BigInt::from(*i)),
            SignedIntegerRepr::U128(u) => Cow::Owned(BigInt::from(*u)),
            SignedIntegerRepr::Big(n) => Cow::Borrowed(n),
        }
    }
}

//--

impl From<isize> for SignedInteger {
    fn from(v: isize) -> Self {
        SignedInteger(SignedIntegerRepr::I128(v as i128))
    }
}

impl From<usize> for SignedInteger {
    fn from(v: usize) -> Self {
        SignedInteger(SignedIntegerRepr::U128(v as u128))
    }
}

impl TryFrom<&SignedInteger> for isize {
    type Error = ();
    fn try_from(v: &SignedInteger) -> Result<Self, Self::Error> {
        i128::try_from(v)?.try_into().map_err(|_| ())
    }
}

impl TryFrom<&SignedInteger> for usize {
    type Error = ();
    fn try_from(v: &SignedInteger) -> Result<Self, Self::Error> {
        u128::try_from(v)?.try_into().map_err(|_| ())
    }
}