use crate::alphabet::Alphabet;
#[allow(clippy::upper_case_acronyms)]
pub enum Rotor {
I,
II,
III,
IV,
V,
VI,
VII,
VIII,
BETA,
}
impl TryFrom<u8> for Rotor {
type Error = anyhow::Error;
fn try_from(value: u8) -> Result<Self, Self::Error> {
Ok(match value {
1 => Self::I,
2 => Self::II,
3 => Self::III,
4 => Self::IV,
5 => Self::V,
6 => Self::VI,
7 => Self::VII,
8 => Self::VIII,
9 => Self::BETA,
_ => anyhow::bail!("Rotor number out of range: {value}"),
})
}
}
pub trait TryIntoRotors {
fn try_into_rotors(self) -> anyhow::Result<(Rotor, Rotor, Rotor)>;
}
impl TryIntoRotors for (u8, u8, u8) {
fn try_into_rotors(self) -> anyhow::Result<(Rotor, Rotor, Rotor)> {
Ok((self.0.try_into()?, self.1.try_into()?, self.2.try_into()?))
}
}
impl Rotor {
pub fn alphabet(&self) -> Alphabet {
Alphabet::new(match self {
Self::I => "EKMFLGDQVZNTOWYHXUSPAIBRCJ",
Self::II => "AJDKSIRUXBLHWTMCQGZNPYFVOE",
Self::III => "BDFHJLCPRTXVZNYEIWGAKMUSQO",
Self::IV => "ESOVPZJAYQUIRHXLNFTGKDCMWB",
Self::V => "VZBRGITYUPSDNHLXAWMJQOFECK",
Self::VI => "JPGVOUMFYQBENHZRDKASXLICTW",
Self::VII => "NZJHGRCXMYSWBOUFAIVLPEKQDT",
Self::VIII => "FKQHTLXOCBJSPDZRAMEWNIUYGV",
Self::BETA => "LEYJVCNIXWPBQMDRTAKZGFUHOS",
})
.unwrap()
}
pub const fn notches(&self) -> &'static [char] {
match self {
Self::I => &['Q'],
Self::II => &['E'],
Self::III => &['V'],
Self::IV => &['J'],
Self::V => &['Z'],
Self::VI => &['M', 'Z'],
Self::VII => &['M', 'Z'],
Self::VIII => &['M', 'Z'],
Self::BETA => &[],
}
}
}