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 { 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 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 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 { 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 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', } } }