rs_teststand/expression/operator/
assignment.rs1use super::Arity;
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
14pub enum AssignmentOperator {
15 Assign,
17 Add,
19 Subtract,
21 Multiply,
23 Divide,
25 Modulo,
27 Xor,
29 Or,
31 And,
33}
34
35impl AssignmentOperator {
36 pub const ALL: [Self; 9] = [
38 Self::Assign,
39 Self::Add,
40 Self::Subtract,
41 Self::Multiply,
42 Self::Divide,
43 Self::Modulo,
44 Self::Xor,
45 Self::Or,
46 Self::And,
47 ];
48
49 #[must_use]
51 pub const fn symbol(self) -> &'static str {
52 match self {
53 Self::Assign => "=",
54 Self::Add => "+=",
55 Self::Subtract => "-=",
56 Self::Multiply => "*=",
57 Self::Divide => "/=",
58 Self::Modulo => "%=",
59 Self::Xor => "^=",
60 Self::Or => "|=",
61 Self::And => "&=",
62 }
63 }
64
65 #[must_use]
67 #[allow(
68 clippy::unused_self,
69 reason = "uniform surface across operator families"
70 )]
71 pub const fn arity(self) -> Arity {
72 Arity::Binary
73 }
74
75 #[must_use]
81 #[allow(
82 clippy::unused_self,
83 reason = "uniform surface across operator families"
84 )]
85 pub const fn precedence(self) -> Option<u8> {
86 None
87 }
88}
89
90#[cfg(test)]
91mod tests {
92 use super::AssignmentOperator;
93
94 #[test]
95 fn precedence_is_reported_as_unknown_rather_than_invented() {
96 for operator in AssignmentOperator::ALL {
97 assert_eq!(operator.precedence(), None, "{operator:?}");
98 }
99 }
100
101 #[test]
102 fn every_compound_form_ends_in_the_assignment_symbol() {
103 for operator in AssignmentOperator::ALL {
104 assert!(operator.symbol().ends_with('='), "{operator:?}");
105 }
106 }
107
108 #[test]
109 fn every_assignment_has_a_distinct_symbol() {
110 let mut symbols: Vec<&str> = AssignmentOperator::ALL
111 .iter()
112 .map(|op| op.symbol())
113 .collect();
114 symbols.sort_unstable();
115 let count = symbols.len();
116 symbols.dedup();
117 assert_eq!(symbols.len(), count);
118 }
119}