use super::Arity;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum AssignmentOperator {
Assign,
Add,
Subtract,
Multiply,
Divide,
Modulo,
Xor,
Or,
And,
}
impl AssignmentOperator {
pub const ALL: [Self; 9] = [
Self::Assign,
Self::Add,
Self::Subtract,
Self::Multiply,
Self::Divide,
Self::Modulo,
Self::Xor,
Self::Or,
Self::And,
];
#[must_use]
pub const fn symbol(self) -> &'static str {
match self {
Self::Assign => "=",
Self::Add => "+=",
Self::Subtract => "-=",
Self::Multiply => "*=",
Self::Divide => "/=",
Self::Modulo => "%=",
Self::Xor => "^=",
Self::Or => "|=",
Self::And => "&=",
}
}
#[must_use]
#[allow(
clippy::unused_self,
reason = "uniform surface across operator families"
)]
pub const fn arity(self) -> Arity {
Arity::Binary
}
#[must_use]
#[allow(
clippy::unused_self,
reason = "uniform surface across operator families"
)]
pub const fn precedence(self) -> Option<u8> {
None
}
}
#[cfg(test)]
mod tests {
use super::AssignmentOperator;
#[test]
fn precedence_is_reported_as_unknown_rather_than_invented() {
for operator in AssignmentOperator::ALL {
assert_eq!(operator.precedence(), None, "{operator:?}");
}
}
#[test]
fn every_compound_form_ends_in_the_assignment_symbol() {
for operator in AssignmentOperator::ALL {
assert!(operator.symbol().ends_with('='), "{operator:?}");
}
}
#[test]
fn every_assignment_has_a_distinct_symbol() {
let mut symbols: Vec<&str> = AssignmentOperator::ALL
.iter()
.map(|op| op.symbol())
.collect();
symbols.sort_unstable();
let count = symbols.len();
symbols.dedup();
assert_eq!(symbols.len(), count);
}
}