smallint 0.2.2

A library for optimized arbitrary precision integers.
Documentation
use crate::smallint::{SmallIntType, SmallUintType};
use crate::SmallInt;
use crate::SmallUint;
use std::cmp::Ordering;

impl PartialEq for SmallUint {
    fn eq(&self, other: &SmallUint) -> bool {
        match (&self.0, &other.0) {
            (SmallUintType::Inline(i), SmallUintType::Inline(j)) => i.eq(j),
            (SmallUintType::Heap((r, s)), SmallUintType::Heap((i, j))) => match j.cmp(s) {
                Ordering::Greater => false,
                Ordering::Less => false,
                Ordering::Equal => {
                    let slice1 = unsafe { core::slice::from_raw_parts(r, *s) };
                    let slice2 = unsafe { core::slice::from_raw_parts(i, *j) };
                    for i in 0..*s {
                        match slice1[s - 1 - i].cmp(&slice2[s - 1 - i]) {
                            Ordering::Less => return false,
                            Ordering::Greater => return false,
                            _ => {}
                        }
                    }
                    true
                }
            },
            (_, _) => false,
        }
    }
}

impl Eq for SmallUint {}

impl PartialOrd for SmallUint {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        match (&self.0, &other.0) {
            (SmallUintType::Inline(i), SmallUintType::Inline(j)) => Some(i.cmp(j)),
            (SmallUintType::Inline(_), SmallUintType::Heap((_, _))) => Some(Ordering::Less),
            (SmallUintType::Heap((_, _)), SmallUintType::Inline(_)) => Some(Ordering::Greater),
            (SmallUintType::Heap((r, s)), SmallUintType::Heap((i, j))) => match j.cmp(s) {
                Ordering::Greater => Some(Ordering::Less),
                Ordering::Less => Some(Ordering::Greater),
                Ordering::Equal => {
                    let slice1 = unsafe { core::slice::from_raw_parts(r, *s) };
                    let slice2 = unsafe { core::slice::from_raw_parts(i, *j) };
                    for i in 0..*s {
                        match slice1[s - 1 - i].cmp(&slice2[s - 1 - i]) {
                            Ordering::Less => return Some(Ordering::Less),
                            Ordering::Greater => return Some(Ordering::Greater),
                            _ => {}
                        }
                    }
                    Some(Ordering::Equal)
                }
            },
        }
    }
}

impl PartialEq for SmallInt {
    fn eq(&self, other: &Self) -> bool {
        match (&self.0, &other.0) {
            (SmallIntType::Inline(i), SmallIntType::Inline(j)) => i.eq(j),
            (SmallIntType::Heap((r, s)), SmallIntType::Heap((i, j))) => {
                if s.signum() != j.signum() {
                    return false;
                }

                match j.cmp(s) {
                    Ordering::Greater => false,
                    Ordering::Less => false,
                    Ordering::Equal => {
                        let us = usize::try_from(s.abs()).unwrap();
                        let uj = usize::try_from(j.abs()).unwrap();
                        let slice1 = unsafe { core::slice::from_raw_parts(r, us) };
                        let slice2 = unsafe { core::slice::from_raw_parts(i, uj) };
                        for i in 0..*s {
                            match slice1[(s - 1 - i) as usize].cmp(&slice2[(s - 1 - i) as usize]) {
                                Ordering::Less => return false,
                                Ordering::Greater => return false,
                                _ => {}
                            }
                        }
                        true
                    }
                }
            }
            (_, _) => false,
        }
    }
}

impl Eq for SmallInt {}

impl PartialOrd for SmallInt {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        let a_sign;
        match &self.0 {
            SmallIntType::Inline(i) => a_sign = i.signum() as i8,
            SmallIntType::Heap((_, s)) => a_sign = s.signum() as i8,
        }

        let b_sign;
        match &other.0 {
            SmallIntType::Inline(i) => b_sign = i.signum() as i8,
            SmallIntType::Heap((_, s)) => b_sign = s.signum() as i8,
        }

        match (a_sign, b_sign) {
            x if (x.0 >= 0 && x.1 < 0) => Some(Ordering::Greater),

            x if (x.0 < 0 && x.1 >= 0) => Some(Ordering::Less),

            x if (x.0 >= 0 && x.1 >= 0) => SmallUint::from_smallint_unsigned(self.clone())
                .partial_cmp(&SmallUint::from_smallint_unsigned(other.clone())),

            x if (x.0 < 0 && x.1 < 0) => SmallUint::from_smallint_unsigned(other.clone())
                .partial_cmp(&SmallUint::from_smallint_unsigned(self.clone())),

            (_, _) => None,
        }
    }
}

impl Ord for SmallInt {
    fn cmp(&self, other: &Self) -> Ordering {
        self.partial_cmp(other).expect("This should not happen.")
    }
}