1use core::hash::Hash;
2use core::hash::Hasher;
3
4use nom::bytes::complete::tag;
5use nom::character::complete::space0;
6use nom::combinator::map;
7use nom::sequence::preceded;
8use nom::IResult;
9use nom::Parser;
10
11#[derive(Clone, Debug)]
13pub enum PosVal {
14 A(f64),
16 B(f64),
18 C(f64),
20
21 E(f64),
23 F(f64),
25
26 S(f64),
28
29 U(f64),
31 V(f64),
33
34 X(f64),
36 Y(f64),
38 Z(f64),
40 W(f64),
42}
43
44impl Eq for PosVal {}
45
46impl PartialEq for PosVal {
50 fn eq(&self, other: &Self) -> bool {
51 match (self, other) {
52 (Self::A(x), Self::A(y))
53 | (Self::B(x), Self::B(y))
54 | (Self::C(x), Self::C(y))
55 | (Self::E(x), Self::E(y))
56 | (Self::F(x), Self::F(y))
57 | (Self::S(x), Self::S(y))
58 | (Self::U(x), Self::U(y))
59 | (Self::V(x), Self::V(y))
60 | (Self::W(x), Self::W(y))
61 | (Self::X(x), Self::X(y))
62 | (Self::Y(x), Self::Y(y))
63 | (Self::Z(x), Self::Z(y)) => x.to_bits() == y.to_bits(),
64 _ => false,
65 }
66 }
67}
68
69impl Hash for PosVal {
78 fn hash<H: Hasher>(&self, state: &mut H) {
79 match self {
80 Self::A(_) => "A".hash(state),
81 Self::B(_) => "B".hash(state),
82 Self::C(_) => "C".hash(state),
83 Self::E(_) => "E".hash(state),
84 Self::F(_) => "F".hash(state),
85 Self::S(_) => "S".hash(state),
86 Self::U(_) => "U".hash(state),
87 Self::V(_) => "V".hash(state),
88 Self::W(_) => "W".hash(state),
89 Self::X(_) => "X".hash(state),
90 Self::Y(_) => "Y".hash(state),
91 Self::Z(_) => "Z".hash(state),
92 }
93 }
94}
95
96macro_rules! parse_val {
103 ($name:ident, $tag:literal, $variant:ident) => {
104 #[doc = "Extracts"]
105 #[doc = stringify!($tag)]
106 #[doc = " parameter"]
107 #[doc = ""]
108 #[doc = "# Errors"]
109 #[doc = " When match fails."]
110 pub fn $name(i: &str) -> IResult<&str, PosVal> {
111 map(
112 preceded((space0, tag($tag)), crate::double::double_no_exponent),
113 PosVal::$variant,
114 )
115 .parse(i)
116 }
117 };
118}
119
120parse_val!(parse_a, "A", A);
121parse_val!(parse_b, "B", B);
122parse_val!(parse_c, "C", C);
123parse_val!(parse_e, "E", E);
125parse_val!(parse_f, "F", F);
126parse_val!(parse_s, "S", S);
127parse_val!(parse_u, "U", U);
129parse_val!(parse_v, "V", V);
130parse_val!(parse_w, "W", W);
131parse_val!(parse_x, "X", X);
133parse_val!(parse_y, "Y", Y);
134parse_val!(parse_z, "Z", Z);
135#[cfg(test)]
137mod test {
138 use super::*;
139
140 #[test]
141 fn pos_value_equality() {
142 assert!(PosVal::A(95.0) == PosVal::A(95.0));
144
145 assert!(PosVal::A(95.0) != PosVal::B(9.0));
147
148 assert!(PosVal::A(95.0) != PosVal::B(95.0));
150 }
151}