212 lines
5 KiB
Rust
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',
|
|
}
|
|
}
|
|
}
|