use core::hash::Hash;
use core::hash::Hasher;
use nom::IResult;
use nom::Parser;
use nom::bytes::complete::tag;
use nom::character::complete::space0;
use nom::combinator::map;
use nom::sequence::preceded;
#[derive(Clone, Debug)]
pub enum PosVal {
A(f64),
B(f64),
C(f64),
E(f64),
F(f64),
S(f64),
U(f64),
V(f64),
X(f64),
Y(f64),
Z(f64),
W(f64),
}
impl Eq for PosVal {}
impl PartialEq for PosVal {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(Self::A(x), Self::A(y))
| (Self::B(x), Self::B(y))
| (Self::C(x), Self::C(y))
| (Self::E(x), Self::E(y))
| (Self::F(x), Self::F(y))
| (Self::S(x), Self::S(y))
| (Self::U(x), Self::U(y))
| (Self::V(x), Self::V(y))
| (Self::W(x), Self::W(y))
| (Self::X(x), Self::X(y))
| (Self::Y(x), Self::Y(y))
| (Self::Z(x), Self::Z(y)) => x.to_bits() == y.to_bits(),
_ => false,
}
}
}
impl Hash for PosVal {
fn hash<H: Hasher>(&self, state: &mut H) {
match self {
Self::A(_) => "A".hash(state),
Self::B(_) => "B".hash(state),
Self::C(_) => "C".hash(state),
Self::E(_) => "E".hash(state),
Self::F(_) => "F".hash(state),
Self::S(_) => "S".hash(state),
Self::U(_) => "U".hash(state),
Self::V(_) => "V".hash(state),
Self::W(_) => "W".hash(state),
Self::X(_) => "X".hash(state),
Self::Y(_) => "Y".hash(state),
Self::Z(_) => "Z".hash(state),
}
}
}
macro_rules! parse_val {
($name:ident, $tag:literal, $variant:ident) => {
#[doc = "Extracts"]
#[doc = stringify!($tag)]
#[doc = " parameter"]
#[doc = ""]
#[doc = "# Errors"]
#[doc = " When match fails."]
pub fn $name(i: &str) -> IResult<&str, PosVal> {
map(
preceded((space0, tag($tag)), crate::double::double_no_exponent),
PosVal::$variant,
)
.parse(i)
}
};
}
parse_val!(parse_a, "A", A);
parse_val!(parse_b, "B", B);
parse_val!(parse_c, "C", C);
parse_val!(parse_e, "E", E);
parse_val!(parse_f, "F", F);
parse_val!(parse_s, "S", S);
parse_val!(parse_u, "U", U);
parse_val!(parse_v, "V", V);
parse_val!(parse_w, "W", W);
parse_val!(parse_x, "X", X);
parse_val!(parse_y, "Y", Y);
parse_val!(parse_z, "Z", Z);
#[cfg(test)]
mod test {
use super::*;
#[test]
fn pos_value_equality() {
assert!(PosVal::A(95.0) == PosVal::A(95.0));
assert!(PosVal::A(95.0) != PosVal::B(9.0));
assert!(PosVal::A(95.0) != PosVal::B(95.0));
}
}