#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum Sign {
Positive = 1,
Negative = -1,
}
pub use Sign::*;
impl Sign {
pub fn to_isize(self) -> isize {
self.into()
}
pub fn to_i64(self) -> i64 {
self.into()
}
pub fn to_i32(self) -> i32 {
self.into()
}
pub fn to_i16(self) -> i16 {
self.into()
}
pub fn to_i8(self) -> i16 {
self.into()
}
}
impl std::ops::Neg for Sign {
type Output = Self;
fn neg(self) -> Self {
match self {
Positive => Negative,
Negative => Positive,
}
}
}
impl<T: std::ops::Neg<Output = T>> std::ops::Mul<T> for Sign {
type Output = T;
fn mul(self, rhs: T) -> T {
match self {
Positive => rhs,
Negative => -rhs,
}
}
}
impl std::str::FromStr for Sign {
type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"+1" => Ok(Positive),
"-1" => Ok(Negative),
"Positive" => Ok(Positive),
"Negative" => Ok(Negative),
_ => Err(()),
}
}
}
impl std::fmt::Display for Sign {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(match self {
Positive => "+1",
Negative => "-1",
})
}
}
pub trait Signed {
fn sign(&self) -> Option<Sign>;
}
macro_rules! impl_traits_for_int {
($($int_type: ty),*) => {
$(
impl From<Sign> for $int_type {
fn from(sign: Sign) -> $int_type {
match sign {
Positive => 1,
Negative => -1,
}
}
}
impl Signed for $int_type {
fn sign(&self) -> Option<Sign> {
match self.cmp(&0) {
std::cmp::Ordering::Equal => None,
std::cmp::Ordering::Greater => Some(Positive),
std::cmp::Ordering::Less => Some(Negative),
}
}
}
)*
};
}
impl_traits_for_int!(isize, i64, i32, i16, i8);
impl From<Sign> for f64 {
fn from(sign: Sign) -> f64 {
match sign {
Positive => 1.0,
Negative => -1.0,
}
}
}
impl From<Sign> for f32 {
fn from(sign: Sign) -> f32 {
match sign {
Positive => 1.0,
Negative => -1.0,
}
}
}
impl Signed for f64 {
fn sign(&self) -> Option<Sign> {
match self.signum().partial_cmp(&0.0) {
Some(std::cmp::Ordering::Greater) => Some(Positive),
Some(std::cmp::Ordering::Less) => Some(Negative),
_ => None,
}
}
}
impl Signed for f32 {
fn sign(&self) -> Option<Sign> {
match self.signum().partial_cmp(&0.0) {
Some(std::cmp::Ordering::Greater) => Some(Positive),
Some(std::cmp::Ordering::Less) => Some(Negative),
_ => None,
}
}
}
#[cfg(feature = "serde")]
#[test]
fn test_serde() {
assert_eq!(serde_json::to_string(&Positive).unwrap(), "\"Positive\"");
assert_eq!(serde_json::to_string(&Negative).unwrap(), "\"Negative\"");
}