#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Arrow {
To,
From,
DoubleTo,
DoubleFrom,
}
pub struct ArrowInfo {
pub name: &'static str,
pub right: bool,
pub body: char,
pub latex: &'static str,
}
pub static ARROW_NAMES: phf::Map<&'static str, Arrow> = phf::phf_map! {
"xto" | "xrightarrow" => Arrow::To,
"xfrom" | "xleftarrow" => Arrow::From,
"xTo" | "xRightarrow" => Arrow::DoubleTo,
"xFrom" | "xLeftarrow" => Arrow::DoubleFrom,
};
impl Arrow {
pub const ALL: [Arrow; 4] = [Arrow::To, Arrow::From, Arrow::DoubleTo, Arrow::DoubleFrom];
#[rustfmt::skip]
pub const fn info(self) -> &'static ArrowInfo {
match self {
Arrow::To => &ArrowInfo { name: "xto", right: true, body: '─', latex: "xrightarrow" },
Arrow::From => &ArrowInfo { name: "xfrom", right: false, body: '─', latex: "xleftarrow" },
Arrow::DoubleTo => &ArrowInfo { name: "xTo", right: true, body: '═', latex: "xRightarrow" },
Arrow::DoubleFrom => &ArrowInfo { name: "xFrom", right: false, body: '═', latex: "xLeftarrow" },
}
}
pub fn of_name(name: &str) -> Option<Arrow> {
ARROW_NAMES.get(name).copied()
}
pub fn right(self) -> bool {
self.info().right
}
pub fn name(self) -> &'static str {
self.info().name
}
pub fn body(self) -> char {
self.info().body
}
pub fn latex(self) -> &'static str {
self.info().latex
}
pub fn of_body(body: char, right: bool) -> Option<Arrow> {
Arrow::ALL
.into_iter()
.find(|a| a.body() == body && a.right() == right)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn arrows_are_a_bijection() {
for a in Arrow::ALL {
assert_eq!(Arrow::of_body(a.body(), a.right()), Some(a));
assert!(a.latex().starts_with('x'));
assert_eq!(Arrow::of_name(a.info().name), Some(a));
assert_eq!(Arrow::of_name(a.latex()), Some(a));
}
}
}