enigma-machine/src/letter.rs
2021-04-21 20:47:47 +02:00

212 lines
5 KiB
Rust

use crate::*;
use rand::prelude::*;
use std::{
ops::{Add, Sub},
str::FromStr,
};
pub const AMOUNT_OF_LETTERS: usize = 26;
#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone, PartialOrd, Ord)]
pub enum Letter {
A = 0,
B = 1,
C = 2,
D = 3,
E = 4,
F = 5,
G = 6,
H = 7,
I = 8,
J = 9,
K = 10,
L = 11,
M = 12,
N = 13,
O = 14,
P = 15,
Q = 16,
R = 17,
S = 18,
T = 19,
U = 20,
V = 21,
W = 22,
X = 23,
Y = 24,
Z = 25,
}
impl Letter {
pub fn all() -> Vec<Letter> {
use Letter::*;
vec![
A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z,
]
}
}
impl Add for Letter {
type Output = Letter;
fn add(self, rhs: Self) -> Self::Output {
Letter::from((self as usize + rhs as usize) % 26)
}
}
impl Sub for Letter {
type Output = Letter;
fn sub(self, rhs: Self) -> Self::Output {
let sum = (self as isize - rhs as isize).rem_euclid(26);
Letter::from(sum as usize)
}
}
impl Random for Letter {
fn random() -> Self {
let mut rng = rand::thread_rng();
let num = rng.gen_range(0..AMOUNT_OF_LETTERS);
Letter::from(num)
}
}
impl From<usize> for Letter {
fn from(n: usize) -> Self {
let index = n % 26;
match index {
0 => Letter::A,
1 => Letter::B,
2 => Letter::C,
3 => Letter::D,
4 => Letter::E,
5 => Letter::F,
6 => Letter::G,
7 => Letter::H,
8 => Letter::I,
9 => Letter::J,
10 => Letter::K,
11 => Letter::L,
12 => Letter::M,
13 => Letter::N,
14 => Letter::O,
15 => Letter::P,
16 => Letter::Q,
17 => Letter::R,
18 => Letter::S,
19 => Letter::T,
20 => Letter::U,
21 => Letter::V,
22 => Letter::W,
23 => Letter::X,
24 => Letter::Y,
25 => Letter::Z,
_ => unreachable!(),
}
}
}
impl From<char> for Letter {
fn from(c: char) -> Self {
match c {
'A' => Letter::A,
'B' => Letter::B,
'C' => Letter::C,
'D' => Letter::D,
'E' => Letter::E,
'F' => Letter::F,
'G' => Letter::G,
'H' => Letter::H,
'I' => Letter::I,
'J' => Letter::J,
'K' => Letter::K,
'L' => Letter::L,
'M' => Letter::M,
'N' => Letter::N,
'O' => Letter::O,
'P' => Letter::P,
'Q' => Letter::Q,
'R' => Letter::R,
'S' => Letter::S,
'T' => Letter::T,
'U' => Letter::U,
'V' => Letter::V,
'W' => Letter::W,
'X' => Letter::X,
'Y' => Letter::Y,
'Z' => Letter::Z,
_ => panic!("Tried to parse unknown letter: '{}'", c),
}
}
}
impl FromStr for Letter {
type Err = &'static str;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"A" => Ok(Letter::A),
"B" => Ok(Letter::B),
"C" => Ok(Letter::C),
"D" => Ok(Letter::D),
"E" => Ok(Letter::E),
"F" => Ok(Letter::F),
"G" => Ok(Letter::G),
"H" => Ok(Letter::H),
"I" => Ok(Letter::I),
"J" => Ok(Letter::J),
"K" => Ok(Letter::K),
"L" => Ok(Letter::L),
"M" => Ok(Letter::M),
"N" => Ok(Letter::N),
"O" => Ok(Letter::O),
"P" => Ok(Letter::P),
"Q" => Ok(Letter::Q),
"R" => Ok(Letter::R),
"S" => Ok(Letter::S),
"T" => Ok(Letter::T),
"U" => Ok(Letter::U),
"V" => Ok(Letter::V),
"W" => Ok(Letter::W),
"X" => Ok(Letter::X),
"Y" => Ok(Letter::Y),
"Z" => Ok(Letter::Z),
_ => Err("Failed to parse string as letter"),
}
}
}
impl From<Letter> for char {
fn from(letter: Letter) -> Self {
match letter {
Letter::A => 'A',
Letter::B => 'B',
Letter::C => 'C',
Letter::D => 'D',
Letter::E => 'E',
Letter::F => 'F',
Letter::G => 'G',
Letter::H => 'H',
Letter::I => 'I',
Letter::J => 'J',
Letter::K => 'K',
Letter::L => 'L',
Letter::M => 'M',
Letter::N => 'N',
Letter::O => 'O',
Letter::P => 'P',
Letter::Q => 'Q',
Letter::R => 'R',
Letter::S => 'S',
Letter::T => 'T',
Letter::U => 'U',
Letter::V => 'V',
Letter::W => 'W',
Letter::X => 'X',
Letter::Y => 'Y',
Letter::Z => 'Z',
}
}
}