use core::cmp::Ordering;
use core::fmt::Debug;
use core::ops::Deref;
use ord_subset_trait::*;
#[derive(PartialEq, PartialOrd, Clone, Copy, Debug, Hash)]
pub struct OrdVar<T: PartialOrd + PartialEq>(T);
impl<T: PartialOrd + PartialEq> OrdVar<T> {
#[inline]
pub fn new(data: T) -> OrdVar<T>
where
T: Debug + OrdSubset,
{
if data.is_outside_order() {
panic!(
"Attempted saving data outside of total order into OrdVar: {:?}",
data
)
};
OrdVar(data)
}
#[inline]
pub fn new_checked(data: T) -> Option<OrdVar<T>>
where
T: OrdSubset,
{
match data.is_outside_order() {
true => None,
false => Some(OrdVar(data)),
}
}
#[inline(always)]
pub fn new_unchecked(data: T) -> OrdVar<T> {
OrdVar(data)
}
#[inline(always)]
pub fn into_inner(self) -> T {
self.0
}
}
impl<T: PartialOrd + PartialEq> Eq for OrdVar<T> {}
#[cfg_attr(clippy, allow(clippy::derive_ord_xor_partial_ord))]
impl<T: PartialOrd + PartialEq> Ord for OrdVar<T> {
#[inline]
fn cmp(&self, other: &Self) -> Ordering {
self.partial_cmp(other)
.expect("OrdVar contains value outside total order")
}
}
impl<T: PartialOrd + PartialEq> Deref for OrdVar<T> {
type Target = T;
#[inline(always)]
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T: PartialOrd + PartialEq> AsRef<T> for OrdVar<T> {
#[inline(always)]
fn as_ref(&self) -> &T {
&self.0
}
}
impl<T: Default + OrdSubset + Debug> Default for OrdVar<T> {
#[inline(always)]
fn default() -> Self {
OrdVar::new(T::default())
}
}
#[cfg(feature = "ops")]
mod ops {
#[cfg_attr(rustfmt, rustfmt_skip)]
use core::ops::{Add, Sub, Mul, Div, Rem, BitAnd, BitOr, BitXor, Shl, Shr, Neg, Not,
AddAssign, SubAssign, MulAssign, DivAssign, RemAssign, BitAndAssign, BitOrAssign, BitXorAssign, ShlAssign, ShrAssign,};
use super::OrdVar;
use core::fmt::Debug;
use ord_subset_trait::*;
#[inline(always)]
fn construct<T: OrdSubset + Debug>(t: T) -> OrdVar<T> {
match cfg!(feature = "unchecked_ops") {
true => OrdVar::new_unchecked(t),
false => OrdVar::new(t),
}
}
impl<T, RHS> Add<RHS> for OrdVar<T>
where
T: PartialOrd + PartialEq + Add<RHS>,
T::Output: PartialOrd + PartialEq + Debug + OrdSubset,
{
type Output = OrdVar<T::Output>;
fn add(self, rhs: RHS) -> Self::Output {
construct(self.into_inner().add(rhs))
}
}
impl<T, RHS> Sub<RHS> for OrdVar<T>
where
T: PartialOrd + PartialEq + Sub<RHS>,
T::Output: PartialOrd + PartialEq + Debug + OrdSubset,
{
type Output = OrdVar<T::Output>;
fn sub(self, rhs: RHS) -> Self::Output {
construct(self.into_inner().sub(rhs))
}
}
impl<T, RHS> Mul<RHS> for OrdVar<T>
where
T: PartialOrd + PartialEq + Mul<RHS>,
T::Output: PartialOrd + PartialEq + Debug + OrdSubset,
{
type Output = OrdVar<T::Output>;
fn mul(self, rhs: RHS) -> Self::Output {
construct(self.into_inner().mul(rhs))
}
}
impl<T, RHS> Div<RHS> for OrdVar<T>
where
T: PartialOrd + PartialEq + Div<RHS>,
T::Output: PartialOrd + PartialEq + Debug + OrdSubset,
{
type Output = OrdVar<T::Output>;
fn div(self, rhs: RHS) -> Self::Output {
construct(self.into_inner().div(rhs))
}
}
impl<T, RHS> Rem<RHS> for OrdVar<T>
where
T: PartialOrd + PartialEq + Rem<RHS>,
T::Output: PartialOrd + PartialEq + Debug + OrdSubset,
{
type Output = OrdVar<T::Output>;
fn rem(self, rhs: RHS) -> Self::Output {
construct(self.into_inner().rem(rhs))
}
}
impl<T, RHS> BitAnd<RHS> for OrdVar<T>
where
T: PartialOrd + PartialEq + BitAnd<RHS>,
T::Output: PartialOrd + PartialEq + Debug + OrdSubset,
{
type Output = OrdVar<T::Output>;
fn bitand(self, rhs: RHS) -> Self::Output {
construct(self.into_inner().bitand(rhs))
}
}
impl<T, RHS> BitOr<RHS> for OrdVar<T>
where
T: PartialOrd + PartialEq + BitOr<RHS>,
T::Output: PartialOrd + PartialEq + Debug + OrdSubset,
{
type Output = OrdVar<T::Output>;
fn bitor(self, rhs: RHS) -> Self::Output {
construct(self.into_inner().bitor(rhs))
}
}
impl<T, RHS> BitXor<RHS> for OrdVar<T>
where
T: PartialOrd + PartialEq + BitXor<RHS>,
T::Output: PartialOrd + PartialEq + Debug + OrdSubset,
{
type Output = OrdVar<T::Output>;
fn bitxor(self, rhs: RHS) -> Self::Output {
construct(self.into_inner().bitxor(rhs))
}
}
impl<T, RHS> Shl<RHS> for OrdVar<T>
where
T: PartialOrd + PartialEq + Shl<RHS>,
T::Output: PartialOrd + PartialEq + Debug + OrdSubset,
{
type Output = OrdVar<T::Output>;
fn shl(self, rhs: RHS) -> Self::Output {
construct(self.into_inner().shl(rhs))
}
}
impl<T, RHS> Shr<RHS> for OrdVar<T>
where
T: PartialOrd + PartialEq + Shr<RHS>,
T::Output: PartialOrd + PartialEq + Debug + OrdSubset,
{
type Output = OrdVar<T::Output>;
fn shr(self, rhs: RHS) -> Self::Output {
construct(self.into_inner().shr(rhs))
}
}
impl<T, RHS> AddAssign<RHS> for OrdVar<T>
where
T: PartialOrd + PartialEq + AddAssign<RHS> + OrdSubset,
{
fn add_assign(&mut self, rhs: RHS) {
self.0.add_assign(rhs);
if !cfg!(feature = "unchecked_ops") {
assert!(
!self.0.is_outside_order(),
"Result of {}= operation is outside order",
"+"
);
}
}
}
impl<T, RHS> SubAssign<RHS> for OrdVar<T>
where
T: PartialOrd + PartialEq + SubAssign<RHS> + OrdSubset,
{
fn sub_assign(&mut self, rhs: RHS) {
self.0.sub_assign(rhs);
if !cfg!(feature = "unchecked_ops") {
assert!(
!self.0.is_outside_order(),
"Result of {}= operation is outside order",
"-"
);
}
}
}
impl<T, RHS> MulAssign<RHS> for OrdVar<T>
where
T: PartialOrd + PartialEq + MulAssign<RHS> + OrdSubset,
{
fn mul_assign(&mut self, rhs: RHS) {
self.0.mul_assign(rhs);
if !cfg!(feature = "unchecked_ops") {
assert!(
!self.0.is_outside_order(),
"Result of {}= operation is outside order",
"*"
);
}
}
}
impl<T, RHS> DivAssign<RHS> for OrdVar<T>
where
T: PartialOrd + PartialEq + DivAssign<RHS> + OrdSubset,
{
fn div_assign(&mut self, rhs: RHS) {
self.0.div_assign(rhs);
if !cfg!(feature = "unchecked_ops") {
assert!(
!self.0.is_outside_order(),
"Result of {}= operation is outside order",
"/"
);
}
}
}
impl<T, RHS> RemAssign<RHS> for OrdVar<T>
where
T: PartialOrd + PartialEq + RemAssign<RHS> + OrdSubset,
{
fn rem_assign(&mut self, rhs: RHS) {
self.0.rem_assign(rhs);
if !cfg!(feature = "unchecked_ops") {
assert!(
!self.0.is_outside_order(),
"Result of {}= operation is outside order",
"%"
);
}
}
}
impl<T, RHS> BitAndAssign<RHS> for OrdVar<T>
where
T: PartialOrd + PartialEq + BitAndAssign<RHS> + OrdSubset,
{
fn bitand_assign(&mut self, rhs: RHS) {
self.0.bitand_assign(rhs);
if !cfg!(feature = "unchecked_ops") {
assert!(
!self.0.is_outside_order(),
"Result of {}= operation is outside order",
"&"
);
}
}
}
impl<T, RHS> BitOrAssign<RHS> for OrdVar<T>
where
T: PartialOrd + PartialEq + BitOrAssign<RHS> + OrdSubset,
{
fn bitor_assign(&mut self, rhs: RHS) {
self.0.bitor_assign(rhs);
if !cfg!(feature = "unchecked_ops") {
assert!(
!self.0.is_outside_order(),
"Result of {}= operation is outside order",
"|"
);
}
}
}
impl<T, RHS> BitXorAssign<RHS> for OrdVar<T>
where
T: PartialOrd + PartialEq + BitXorAssign<RHS> + OrdSubset,
{
fn bitxor_assign(&mut self, rhs: RHS) {
self.0.bitxor_assign(rhs);
if !cfg!(feature = "unchecked_ops") {
assert!(
!self.0.is_outside_order(),
"Result of {}= operation is outside order",
"^"
);
}
}
}
impl<T, RHS> ShlAssign<RHS> for OrdVar<T>
where
T: PartialOrd + PartialEq + ShlAssign<RHS> + OrdSubset,
{
fn shl_assign(&mut self, rhs: RHS) {
self.0.shl_assign(rhs);
if !cfg!(feature = "unchecked_ops") {
assert!(
!self.0.is_outside_order(),
"Result of {}= operation is outside order",
"<<"
);
}
}
}
impl<T, RHS> ShrAssign<RHS> for OrdVar<T>
where
T: PartialOrd + PartialEq + ShrAssign<RHS> + OrdSubset,
{
fn shr_assign(&mut self, rhs: RHS) {
self.0.shr_assign(rhs);
if !cfg!(feature = "unchecked_ops") {
assert!(
!self.0.is_outside_order(),
"Result of {}= operation is outside order",
">>"
);
}
}
}
impl<T> Neg for OrdVar<T>
where
T: PartialOrd + PartialEq + Neg,
T::Output: PartialOrd + PartialEq + Debug + OrdSubset,
{
type Output = OrdVar<T::Output>;
fn neg(self) -> Self::Output {
construct(self.into_inner().neg())
}
}
impl<T> Not for OrdVar<T>
where
T: PartialOrd + PartialEq + Not,
T::Output: PartialOrd + PartialEq + Debug + OrdSubset,
{
type Output = OrdVar<T::Output>;
fn not(self) -> Self::Output {
construct(self.into_inner().not())
}
}
}