use core::fmt::{self, Display, Formatter};
use core::str::FromStr;
#[cfg(feature = "enable-serde")]
use serde::{Deserialize, Serialize};
pub trait CondCode: Copy {
#[must_use]
fn inverse(self) -> Self;
#[must_use]
fn reverse(self) -> Self;
}
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
pub enum IntCC {
Equal,
NotEqual,
SignedLessThan,
SignedGreaterThanOrEqual,
SignedGreaterThan,
SignedLessThanOrEqual,
UnsignedLessThan,
UnsignedGreaterThanOrEqual,
UnsignedGreaterThan,
UnsignedLessThanOrEqual,
Overflow,
NotOverflow,
}
impl CondCode for IntCC {
fn inverse(self) -> Self {
use self::IntCC::*;
match self {
Equal => NotEqual,
NotEqual => Equal,
SignedLessThan => SignedGreaterThanOrEqual,
SignedGreaterThanOrEqual => SignedLessThan,
SignedGreaterThan => SignedLessThanOrEqual,
SignedLessThanOrEqual => SignedGreaterThan,
UnsignedLessThan => UnsignedGreaterThanOrEqual,
UnsignedGreaterThanOrEqual => UnsignedLessThan,
UnsignedGreaterThan => UnsignedLessThanOrEqual,
UnsignedLessThanOrEqual => UnsignedGreaterThan,
Overflow => NotOverflow,
NotOverflow => Overflow,
}
}
fn reverse(self) -> Self {
use self::IntCC::*;
match self {
Equal => Equal,
NotEqual => NotEqual,
SignedGreaterThan => SignedLessThan,
SignedGreaterThanOrEqual => SignedLessThanOrEqual,
SignedLessThan => SignedGreaterThan,
SignedLessThanOrEqual => SignedGreaterThanOrEqual,
UnsignedGreaterThan => UnsignedLessThan,
UnsignedGreaterThanOrEqual => UnsignedLessThanOrEqual,
UnsignedLessThan => UnsignedGreaterThan,
UnsignedLessThanOrEqual => UnsignedGreaterThanOrEqual,
Overflow => Overflow,
NotOverflow => NotOverflow,
}
}
}
impl IntCC {
pub fn all() -> &'static [IntCC] {
&[
IntCC::Equal,
IntCC::NotEqual,
IntCC::SignedLessThan,
IntCC::SignedGreaterThanOrEqual,
IntCC::SignedGreaterThan,
IntCC::SignedLessThanOrEqual,
IntCC::UnsignedLessThan,
IntCC::UnsignedGreaterThanOrEqual,
IntCC::UnsignedGreaterThan,
IntCC::UnsignedLessThanOrEqual,
IntCC::Overflow,
IntCC::NotOverflow,
]
}
pub fn without_equal(self) -> Self {
use self::IntCC::*;
match self {
SignedGreaterThan | SignedGreaterThanOrEqual => SignedGreaterThan,
SignedLessThan | SignedLessThanOrEqual => SignedLessThan,
UnsignedGreaterThan | UnsignedGreaterThanOrEqual => UnsignedGreaterThan,
UnsignedLessThan | UnsignedLessThanOrEqual => UnsignedLessThan,
_ => self,
}
}
pub fn unsigned(self) -> Self {
use self::IntCC::*;
match self {
SignedGreaterThan | UnsignedGreaterThan => UnsignedGreaterThan,
SignedGreaterThanOrEqual | UnsignedGreaterThanOrEqual => UnsignedGreaterThanOrEqual,
SignedLessThan | UnsignedLessThan => UnsignedLessThan,
SignedLessThanOrEqual | UnsignedLessThanOrEqual => UnsignedLessThanOrEqual,
_ => self,
}
}
pub fn to_static_str(self) -> &'static str {
use self::IntCC::*;
match self {
Equal => "eq",
NotEqual => "ne",
SignedGreaterThan => "sgt",
SignedGreaterThanOrEqual => "sge",
SignedLessThan => "slt",
SignedLessThanOrEqual => "sle",
UnsignedGreaterThan => "ugt",
UnsignedGreaterThanOrEqual => "uge",
UnsignedLessThan => "ult",
UnsignedLessThanOrEqual => "ule",
Overflow => "of",
NotOverflow => "nof",
}
}
}
impl Display for IntCC {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
f.write_str(self.to_static_str())
}
}
impl FromStr for IntCC {
type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> {
use self::IntCC::*;
match s {
"eq" => Ok(Equal),
"ne" => Ok(NotEqual),
"sge" => Ok(SignedGreaterThanOrEqual),
"sgt" => Ok(SignedGreaterThan),
"sle" => Ok(SignedLessThanOrEqual),
"slt" => Ok(SignedLessThan),
"uge" => Ok(UnsignedGreaterThanOrEqual),
"ugt" => Ok(UnsignedGreaterThan),
"ule" => Ok(UnsignedLessThanOrEqual),
"ult" => Ok(UnsignedLessThan),
"of" => Ok(Overflow),
"nof" => Ok(NotOverflow),
_ => Err(()),
}
}
}
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
pub enum FloatCC {
Ordered,
Unordered,
Equal,
NotEqual,
OrderedNotEqual,
UnorderedOrEqual,
LessThan,
LessThanOrEqual,
GreaterThan,
GreaterThanOrEqual,
UnorderedOrLessThan,
UnorderedOrLessThanOrEqual,
UnorderedOrGreaterThan,
UnorderedOrGreaterThanOrEqual,
}
impl FloatCC {
pub fn all() -> &'static [FloatCC] {
&[
FloatCC::Ordered,
FloatCC::Unordered,
FloatCC::Equal,
FloatCC::NotEqual,
FloatCC::OrderedNotEqual,
FloatCC::UnorderedOrEqual,
FloatCC::LessThan,
FloatCC::LessThanOrEqual,
FloatCC::GreaterThan,
FloatCC::GreaterThanOrEqual,
FloatCC::UnorderedOrLessThan,
FloatCC::UnorderedOrLessThanOrEqual,
FloatCC::UnorderedOrGreaterThan,
FloatCC::UnorderedOrGreaterThanOrEqual,
]
}
}
impl CondCode for FloatCC {
fn inverse(self) -> Self {
use self::FloatCC::*;
match self {
Ordered => Unordered,
Unordered => Ordered,
Equal => NotEqual,
NotEqual => Equal,
OrderedNotEqual => UnorderedOrEqual,
UnorderedOrEqual => OrderedNotEqual,
LessThan => UnorderedOrGreaterThanOrEqual,
LessThanOrEqual => UnorderedOrGreaterThan,
GreaterThan => UnorderedOrLessThanOrEqual,
GreaterThanOrEqual => UnorderedOrLessThan,
UnorderedOrLessThan => GreaterThanOrEqual,
UnorderedOrLessThanOrEqual => GreaterThan,
UnorderedOrGreaterThan => LessThanOrEqual,
UnorderedOrGreaterThanOrEqual => LessThan,
}
}
fn reverse(self) -> Self {
use self::FloatCC::*;
match self {
Ordered => Ordered,
Unordered => Unordered,
Equal => Equal,
NotEqual => NotEqual,
OrderedNotEqual => OrderedNotEqual,
UnorderedOrEqual => UnorderedOrEqual,
LessThan => GreaterThan,
LessThanOrEqual => GreaterThanOrEqual,
GreaterThan => LessThan,
GreaterThanOrEqual => LessThanOrEqual,
UnorderedOrLessThan => UnorderedOrGreaterThan,
UnorderedOrLessThanOrEqual => UnorderedOrGreaterThanOrEqual,
UnorderedOrGreaterThan => UnorderedOrLessThan,
UnorderedOrGreaterThanOrEqual => UnorderedOrLessThanOrEqual,
}
}
}
impl Display for FloatCC {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
use self::FloatCC::*;
f.write_str(match *self {
Ordered => "ord",
Unordered => "uno",
Equal => "eq",
NotEqual => "ne",
OrderedNotEqual => "one",
UnorderedOrEqual => "ueq",
LessThan => "lt",
LessThanOrEqual => "le",
GreaterThan => "gt",
GreaterThanOrEqual => "ge",
UnorderedOrLessThan => "ult",
UnorderedOrLessThanOrEqual => "ule",
UnorderedOrGreaterThan => "ugt",
UnorderedOrGreaterThanOrEqual => "uge",
})
}
}
impl FromStr for FloatCC {
type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> {
use self::FloatCC::*;
match s {
"ord" => Ok(Ordered),
"uno" => Ok(Unordered),
"eq" => Ok(Equal),
"ne" => Ok(NotEqual),
"one" => Ok(OrderedNotEqual),
"ueq" => Ok(UnorderedOrEqual),
"lt" => Ok(LessThan),
"le" => Ok(LessThanOrEqual),
"gt" => Ok(GreaterThan),
"ge" => Ok(GreaterThanOrEqual),
"ult" => Ok(UnorderedOrLessThan),
"ule" => Ok(UnorderedOrLessThanOrEqual),
"ugt" => Ok(UnorderedOrGreaterThan),
"uge" => Ok(UnorderedOrGreaterThanOrEqual),
_ => Err(()),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::string::ToString;
#[test]
fn int_inverse() {
for r in IntCC::all() {
let cc = *r;
let inv = cc.inverse();
assert!(cc != inv);
assert_eq!(inv.inverse(), cc);
}
}
#[test]
fn int_reverse() {
for r in IntCC::all() {
let cc = *r;
let rev = cc.reverse();
assert_eq!(rev.reverse(), cc);
}
}
#[test]
fn int_display() {
for r in IntCC::all() {
let cc = *r;
assert_eq!(cc.to_string().parse(), Ok(cc));
}
assert_eq!("bogus".parse::<IntCC>(), Err(()));
}
#[test]
fn float_inverse() {
for r in FloatCC::all() {
let cc = *r;
let inv = cc.inverse();
assert!(cc != inv);
assert_eq!(inv.inverse(), cc);
}
}
#[test]
fn float_reverse() {
for r in FloatCC::all() {
let cc = *r;
let rev = cc.reverse();
assert_eq!(rev.reverse(), cc);
}
}
#[test]
fn float_display() {
for r in FloatCC::all() {
let cc = *r;
assert_eq!(cc.to_string().parse(), Ok(cc));
}
assert_eq!("bogus".parse::<FloatCC>(), Err(()));
}
}