1use super::utils::DEFAULT_ROTOR_NUM;
4
5use super::{
6 components::{Plugboard, Reflector, Rotor, Wheel},
7 utils::Letter,
8};
9
10pub struct Unset;
12
13#[derive(Debug)]
14pub struct EnigmaSettings<const ROTOR_NUM: usize = DEFAULT_ROTOR_NUM> {
16 pub rotors: [Rotor; ROTOR_NUM],
18 pub plugboard: Plugboard,
20 pub reflector: Reflector,
22 pub ringstellung: [u8; ROTOR_NUM],
24 pub grundstellung: [Letter; ROTOR_NUM],
26}
27
28#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
29pub struct Enigma<R, P, O, const ROTOR_NUM: usize = DEFAULT_ROTOR_NUM> {
63 rotors: R,
64 plugboard: P,
65 reflector: O,
66}
67
68impl Default for Enigma<Unset, Unset, Unset, DEFAULT_ROTOR_NUM> {
69 fn default() -> Self {
75 Enigma {
76 rotors: Unset,
77 plugboard: Unset,
78 reflector: Unset,
79 }
80 }
81}
82
83impl Enigma<Unset, Unset, Unset> {
84 #[must_use]
129 pub fn new<const ROTOR_NUM: usize>(
130 config: &EnigmaSettings<ROTOR_NUM>,
131 ) -> Enigma<Wheel<ROTOR_NUM>, Plugboard, Reflector, ROTOR_NUM> {
132 let mut enigma = Enigma {
133 rotors: Wheel::new(config.rotors),
134 plugboard: config.plugboard,
135 reflector: config.reflector,
136 };
137 enigma.set_grundstellung(config.grundstellung);
138 enigma.set_ringstellung(config.ringstellung);
139 enigma
140 }
141}
142
143impl<AnyRotor, AnyPlugboard, AnyReflector, const ROTOR_NUM: usize>
144 Enigma<AnyRotor, AnyPlugboard, AnyReflector, ROTOR_NUM>
145{
146 pub fn set_rotors(self, rotors: Wheel) -> Enigma<Wheel, AnyPlugboard, AnyReflector, ROTOR_NUM> {
148 Enigma {
149 rotors,
150 plugboard: self.plugboard,
151 reflector: self.reflector,
152 }
153 }
154
155 pub fn set_plugboard(
157 self,
158 plugboard: Plugboard,
159 ) -> Enigma<AnyRotor, Plugboard, AnyReflector, ROTOR_NUM> {
160 Enigma {
161 rotors: self.rotors,
162 plugboard,
163 reflector: self.reflector,
164 }
165 }
166
167 pub fn set_reflector(
169 self,
170 reflector: Reflector,
171 ) -> Enigma<AnyRotor, AnyPlugboard, Reflector, ROTOR_NUM> {
172 Enigma {
173 rotors: self.rotors,
174 plugboard: self.plugboard,
175 reflector,
176 }
177 }
178}
179
180impl<AnyPlugboard, AnyReflector, const ROTOR_NUM: usize>
181 Enigma<Wheel<ROTOR_NUM>, AnyPlugboard, AnyReflector, ROTOR_NUM>
182{
183 pub fn set_grundstellung(
185 &mut self,
186 positions: [Letter; ROTOR_NUM],
187 ) -> &mut Enigma<Wheel<ROTOR_NUM>, AnyPlugboard, AnyReflector, ROTOR_NUM> {
188 self.rotors.set_positions(positions);
189 self
190 }
191
192 pub fn set_ringstellung(
194 &mut self,
195 positions: [u8; ROTOR_NUM],
196 ) -> &mut Enigma<Wheel<ROTOR_NUM>, AnyPlugboard, AnyReflector, ROTOR_NUM> {
197 self.rotors.set_ring_wiring_offset(positions);
198 self
199 }
200
201 pub fn get_grundstellung(&self) -> [Letter; ROTOR_NUM] {
203 self.rotors.get_positions()
204 }
205}
206
207impl<const ROTOR_NUM: usize> Enigma<Wheel<ROTOR_NUM>, Plugboard, Reflector, ROTOR_NUM> {
208 pub fn encrypt_letter(&mut self, letter: Letter) -> Letter {
210 self.rotors.step();
211 let left = self.rotors.forward(self.plugboard[letter]);
212 self.plugboard[self.rotors.backward(self.reflector[left])]
213 }
214
215 pub fn encrypt_char(&mut self, letter: char) -> char {
217 match Letter::try_from(letter) {
218 Ok(a) => self.encrypt_letter(a).into(),
219 Err(_) => letter,
220 }
221 }
222}
223
224#[cfg(test)]
225mod tests {
226 use super::super::components::{
227 REFLECTOR_A, REFLECTOR_B, ROTOR_I, ROTOR_II, ROTOR_III, ROTOR_IV, ROTOR_V,
228 };
229 use super::*;
230 use core::str::FromStr;
231
232 #[test]
233 fn test_machine() {
234 let enigma = Enigma::default();
235 let enigma = enigma.set_rotors(Wheel::new([ROTOR_I, ROTOR_II, ROTOR_III]));
236 let enigma = enigma.set_plugboard(Plugboard::new(&[]));
237 let enigma = enigma.set_reflector(REFLECTOR_A);
238 let mut enigma = enigma.set_rotors(Wheel::new([ROTOR_III, ROTOR_II, ROTOR_I]));
239 enigma.encrypt_letter(Letter::A);
240 }
241
242 #[test]
243 fn test_letter() {
244 let mut enigma = Enigma::default()
245 .set_rotors(Wheel::new([ROTOR_II, ROTOR_IV, ROTOR_V]))
246 .set_reflector(REFLECTOR_B)
247 .set_plugboard(Plugboard::from_str("AV,BS,CG,DL,FU,HZ,IN,KM,OW,RX").unwrap());
248 enigma
249 .set_grundstellung([Letter::B, Letter::L, Letter::A])
250 .set_ringstellung([2, 21, 12]);
251 assert_eq!(Letter::A, enigma.encrypt_letter(Letter::E));
252 assert_eq!(Letter::U, enigma.encrypt_letter(Letter::D));
253 assert_eq!(Letter::F, enigma.encrypt_letter(Letter::P));
254 assert_eq!(Letter::K, enigma.encrypt_letter(Letter::U));
255 assert_eq!(Letter::L, enigma.encrypt_letter(Letter::D));
256 assert_eq!(Letter::X, enigma.encrypt_letter(Letter::N));
257 assert_eq!(Letter::A, enigma.encrypt_letter(Letter::R));
258 assert_eq!(Letter::B, enigma.encrypt_letter(Letter::G));
259 assert_eq!(Letter::T, enigma.encrypt_letter(Letter::Y));
260 assert_eq!(Letter::E, enigma.encrypt_letter(Letter::S));
261 }
262
263 #[test]
264 fn test_string() {
265 let mut enigma = Enigma::new(&EnigmaSettings {
266 rotors: [ROTOR_II, ROTOR_IV, ROTOR_V],
267 plugboard: Plugboard::from_str("AV,BS,CG,DL,FU,HZ,IN,KM,OW,RX").unwrap(),
268 reflector: REFLECTOR_B,
269 ringstellung: [2, 21, 12],
270 grundstellung: [Letter::B, Letter::L, Letter::A],
271 });
272 let input = "AUFKLXABTE";
273 let expected = "EDPUDNRGYS".as_bytes();
274 for (i, ch) in input.chars().enumerate() {
275 assert_eq!(expected[i] as char, enigma.encrypt_char(ch));
276 }
277 }
278}