use std::cmp::Ordering;
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Cmp {
Eq,
Ne,
Lt,
Le,
Ge,
Gt,
}
impl Cmp {
#[allow(clippy::result_unit_err)]
pub fn from_sign<S: AsRef<str>>(sign: S) -> Result<Cmp, ()> {
match sign.as_ref().trim() {
"==" | "=" => Ok(Cmp::Eq),
"!=" | "!" | "<>" => Ok(Cmp::Ne),
"<" => Ok(Cmp::Lt),
"<=" => Ok(Cmp::Le),
">=" => Ok(Cmp::Ge),
">" => Ok(Cmp::Gt),
_ => Err(()),
}
}
#[allow(clippy::result_unit_err)]
pub fn from_name<S: AsRef<str>>(sign: S) -> Result<Cmp, ()> {
match sign.as_ref().trim().to_lowercase().as_str() {
"eq" => Ok(Cmp::Eq),
"ne" => Ok(Cmp::Ne),
"lt" => Ok(Cmp::Lt),
"le" => Ok(Cmp::Le),
"ge" => Ok(Cmp::Ge),
"gt" => Ok(Cmp::Gt),
_ => Err(()),
}
}
#[deprecated(since = "0.2.0", note = "use Cmp::from(ord) instead")]
pub fn from_ord(ord: Ordering) -> Cmp {
Self::from(ord)
}
pub fn name<'a>(self) -> &'a str {
match self {
Cmp::Eq => "eq",
Cmp::Ne => "ne",
Cmp::Lt => "lt",
Cmp::Le => "le",
Cmp::Ge => "ge",
Cmp::Gt => "gt",
}
}
#[must_use]
pub fn invert(self) -> Self {
match self {
Cmp::Eq => Cmp::Ne,
Cmp::Ne => Cmp::Eq,
Cmp::Lt => Cmp::Ge,
Cmp::Le => Cmp::Gt,
Cmp::Ge => Cmp::Lt,
Cmp::Gt => Cmp::Le,
}
}
#[must_use]
pub fn opposite(self) -> Self {
match self {
Cmp::Eq => Cmp::Ne,
Cmp::Ne => Cmp::Eq,
Cmp::Lt => Cmp::Gt,
Cmp::Le => Cmp::Ge,
Cmp::Ge => Cmp::Le,
Cmp::Gt => Cmp::Lt,
}
}
#[must_use]
pub fn flip(self) -> Self {
match self {
Cmp::Lt => Cmp::Gt,
Cmp::Le => Cmp::Ge,
Cmp::Ge => Cmp::Le,
Cmp::Gt => Cmp::Lt,
_ => self,
}
}
pub fn sign(self) -> &'static str {
match self {
Cmp::Eq => "==",
Cmp::Ne => "!=",
Cmp::Lt => "<",
Cmp::Le => "<=",
Cmp::Ge => ">=",
Cmp::Gt => ">",
}
}
pub fn factor(self) -> i8 {
match self {
Cmp::Eq | Cmp::Ne => 0,
Cmp::Lt | Cmp::Le => -1,
Cmp::Gt | Cmp::Ge => 1,
}
}
pub fn ord(self) -> Option<Ordering> {
match self {
Cmp::Eq => Some(Ordering::Equal),
Cmp::Lt => Some(Ordering::Less),
Cmp::Gt => Some(Ordering::Greater),
_ => None,
}
}
}
impl From<Ordering> for Cmp {
fn from(ord: Ordering) -> Self {
match ord {
Ordering::Less => Cmp::Lt,
Ordering::Equal => Cmp::Eq,
Ordering::Greater => Cmp::Gt,
}
}
}
#[cfg_attr(tarpaulin, skip)]
#[cfg(test)]
mod tests {
use std::cmp::Ordering;
use super::Cmp;
#[test]
fn from_sign() {
assert_eq!(Cmp::from_sign("==").unwrap(), Cmp::Eq);
assert_eq!(Cmp::from_sign("=").unwrap(), Cmp::Eq);
assert_eq!(Cmp::from_sign("!=").unwrap(), Cmp::Ne);
assert_eq!(Cmp::from_sign("!").unwrap(), Cmp::Ne);
assert_eq!(Cmp::from_sign("<>").unwrap(), Cmp::Ne);
assert_eq!(Cmp::from_sign("<").unwrap(), Cmp::Lt);
assert_eq!(Cmp::from_sign("<=").unwrap(), Cmp::Le);
assert_eq!(Cmp::from_sign(">=").unwrap(), Cmp::Ge);
assert_eq!(Cmp::from_sign(">").unwrap(), Cmp::Gt);
assert_eq!(Cmp::from_sign(" <= ").unwrap(), Cmp::Le);
assert_eq!(Cmp::from_sign("*"), Err(()));
}
#[test]
fn from_name() {
assert_eq!(Cmp::from_name("eq").unwrap(), Cmp::Eq);
assert_eq!(Cmp::from_name("ne").unwrap(), Cmp::Ne);
assert_eq!(Cmp::from_name("lt").unwrap(), Cmp::Lt);
assert_eq!(Cmp::from_name("le").unwrap(), Cmp::Le);
assert_eq!(Cmp::from_name("ge").unwrap(), Cmp::Ge);
assert_eq!(Cmp::from_name("gt").unwrap(), Cmp::Gt);
assert_eq!(Cmp::from_name(" Le ").unwrap(), Cmp::Le);
assert_eq!(Cmp::from_name("abc"), Err(()));
}
#[test]
fn from_ord() {
assert_eq!(Cmp::from(Ordering::Less), Cmp::Lt);
assert_eq!(Cmp::from(Ordering::Equal), Cmp::Eq);
assert_eq!(Cmp::from(Ordering::Greater), Cmp::Gt);
}
#[test]
fn name() {
assert_eq!(Cmp::Eq.name(), "eq");
assert_eq!(Cmp::Ne.name(), "ne");
assert_eq!(Cmp::Lt.name(), "lt");
assert_eq!(Cmp::Le.name(), "le");
assert_eq!(Cmp::Ge.name(), "ge");
assert_eq!(Cmp::Gt.name(), "gt");
}
#[test]
fn invert() {
assert_eq!(Cmp::Ne.invert(), Cmp::Eq);
assert_eq!(Cmp::Eq.invert(), Cmp::Ne);
assert_eq!(Cmp::Ge.invert(), Cmp::Lt);
assert_eq!(Cmp::Gt.invert(), Cmp::Le);
assert_eq!(Cmp::Lt.invert(), Cmp::Ge);
assert_eq!(Cmp::Le.invert(), Cmp::Gt);
}
#[test]
fn opposite() {
assert_eq!(Cmp::Eq.opposite(), Cmp::Ne);
assert_eq!(Cmp::Ne.opposite(), Cmp::Eq);
assert_eq!(Cmp::Lt.opposite(), Cmp::Gt);
assert_eq!(Cmp::Le.opposite(), Cmp::Ge);
assert_eq!(Cmp::Ge.opposite(), Cmp::Le);
assert_eq!(Cmp::Gt.opposite(), Cmp::Lt);
}
#[test]
fn flip() {
assert_eq!(Cmp::Eq.flip(), Cmp::Eq);
assert_eq!(Cmp::Ne.flip(), Cmp::Ne);
assert_eq!(Cmp::Lt.flip(), Cmp::Gt);
assert_eq!(Cmp::Le.flip(), Cmp::Ge);
assert_eq!(Cmp::Ge.flip(), Cmp::Le);
assert_eq!(Cmp::Gt.flip(), Cmp::Lt);
}
#[test]
fn sign() {
assert_eq!(Cmp::Eq.sign(), "==");
assert_eq!(Cmp::Ne.sign(), "!=");
assert_eq!(Cmp::Lt.sign(), "<");
assert_eq!(Cmp::Le.sign(), "<=");
assert_eq!(Cmp::Ge.sign(), ">=");
assert_eq!(Cmp::Gt.sign(), ">");
}
#[test]
fn factor() {
assert_eq!(Cmp::Eq.factor(), 0);
assert_eq!(Cmp::Ne.factor(), 0);
assert_eq!(Cmp::Lt.factor(), -1);
assert_eq!(Cmp::Le.factor(), -1);
assert_eq!(Cmp::Ge.factor(), 1);
assert_eq!(Cmp::Gt.factor(), 1);
}
#[test]
fn ord() {
assert_eq!(Cmp::Eq.ord(), Some(Ordering::Equal));
assert_eq!(Cmp::Ne.ord(), None);
assert_eq!(Cmp::Lt.ord(), Some(Ordering::Less));
assert_eq!(Cmp::Le.ord(), None);
assert_eq!(Cmp::Ge.ord(), None);
assert_eq!(Cmp::Gt.ord(), Some(Ordering::Greater));
}
}