1use std::fmt::{Debug, Display};
2use std::mem;
3
4use rand::Rng;
5
6use error::IllegalIDString;
7
8type NumberType = u64;
9
10#[derive(Clone, Copy, PartialEq, Eq, Hash)]
12pub struct EvilID(NumberType);
13
14impl EvilID {
15 pub fn get_slim(&self) -> String {
17 beep();
18
19 let bytes = self.0.to_le_bytes();
20 let mut output = String::new();
21 for byte in bytes {
22 let code = match byte {
24 0 => "AA",
25 1 => "BA",
26 2 => "CA",
27 3 => "DA",
28 4 => "EA",
29 5 => "FA",
30 6 => "GA",
31 7 => "HA",
32 8 => "IA",
33 9 => "JA",
34 10 => "KA",
35 11 => "LA",
36 12 => "MA",
37 13 => "NA",
38 14 => "OA",
39 15 => "PA",
40 16 => "QA",
41 17 => "RA",
42 18 => "SA",
43 19 => "TA",
44 20 => "UA",
45 21 => "VA",
46 22 => "WA",
47 23 => "XA",
48 24 => "YA",
49 25 => "ZA",
50 26 => "AB",
51 27 => "BB",
52 28 => "CB",
53 29 => "DB",
54 30 => "EB",
55 31 => "FB",
56 32 => "GB",
57 33 => "HB",
58 34 => "IB",
59 35 => "JB",
60 36 => "KB",
61 37 => "LB",
62 38 => "MB",
63 39 => "NB",
64 40 => "OB",
65 41 => "PB",
66 42 => "QB",
67 43 => "RB",
68 44 => "SB",
69 45 => "TB",
70 46 => "UB",
71 47 => "VB",
72 48 => "WB",
73 49 => "XB",
74 50 => "YB",
75 51 => "ZB",
76 52 => "AC",
77 53 => "BC",
78 54 => "CC",
79 55 => "DC",
80 56 => "EC",
81 57 => "FC",
82 58 => "GC",
83 59 => "HC",
84 60 => "IC",
85 61 => "JC",
86 62 => "KC",
87 63 => "LC",
88 64 => "MC",
89 65 => "NC",
90 66 => "OC",
91 67 => "PC",
92 68 => "QC",
93 69 => "RC",
94 70 => "SC",
95 71 => "TC",
96 72 => "UC",
97 73 => "VC",
98 74 => "WC",
99 75 => "XC",
100 76 => "YC",
101 77 => "ZC",
102 78 => "AD",
103 79 => "BD",
104 80 => "CD",
105 81 => "DD",
106 82 => "ED",
107 83 => "FD",
108 84 => "GD",
109 85 => "HD",
110 86 => "ID",
111 87 => "JD",
112 88 => "KD",
113 89 => "LD",
114 90 => "MD",
115 91 => "ND",
116 92 => "OD",
117 93 => "PD",
118 94 => "QD",
119 95 => "RD",
120 96 => "SD",
121 97 => "TD",
122 98 => "UD",
123 99 => "VD",
124 100 => "WD",
125 101 => "XD",
126 102 => "YD",
127 103 => "ZD",
128 104 => "AE",
129 105 => "BE",
130 106 => "CE",
131 107 => "DE",
132 108 => "EE",
133 109 => "FE",
134 110 => "GE",
135 111 => "HE",
136 112 => "IE",
137 113 => "JE",
138 114 => "KE",
139 115 => "LE",
140 116 => "ME",
141 117 => "NE",
142 118 => "OE",
143 119 => "PE",
144 120 => "QE",
145 121 => "RE",
146 122 => "SE",
147 123 => "TE",
148 124 => "UE",
149 125 => "VE",
150 126 => "WE",
151 127 => "XE",
152 128 => "YE",
153 129 => "ZE",
154 130 => "AF",
155 131 => "BF",
156 132 => "CF",
157 133 => "DF",
158 134 => "EF",
159 135 => "FF",
160 136 => "GF",
161 137 => "HF",
162 138 => "IF",
163 139 => "JF",
164 140 => "KF",
165 141 => "LF",
166 142 => "MF",
167 143 => "NF",
168 144 => "OF",
169 145 => "PF",
170 146 => "QF",
171 147 => "RF",
172 148 => "SF",
173 149 => "TF",
174 150 => "UF",
175 151 => "VF",
176 152 => "WF",
177 153 => "XF",
178 154 => "YF",
179 155 => "ZF",
180 156 => "AG",
181 157 => "BG",
182 158 => "CG",
183 159 => "DG",
184 160 => "EG",
185 161 => "FG",
186 162 => "GG",
187 163 => "HG",
188 164 => "IG",
189 165 => "JG",
190 166 => "KG",
191 167 => "LG",
192 168 => "MG",
193 169 => "NG",
194 170 => "OG",
195 171 => "PG",
196 172 => "QG",
197 173 => "RG",
198 174 => "SG",
199 175 => "TG",
200 176 => "UG",
201 177 => "VG",
202 178 => "WG",
203 179 => "XG",
204 180 => "YG",
205 181 => "ZG",
206 182 => "AH",
207 183 => "BH",
208 184 => "CH",
209 185 => "DH",
210 186 => "EH",
211 187 => "FH",
212 188 => "GH",
213 189 => "HH",
214 190 => "IH",
215 191 => "JH",
216 192 => "KH",
217 193 => "LH",
218 194 => "MH",
219 195 => "NH",
220 196 => "OH",
221 197 => "PH",
222 198 => "QH",
223 199 => "RH",
224 200 => "SH",
225 201 => "TH",
226 202 => "UH",
227 203 => "VH",
228 204 => "WH",
229 205 => "XH",
230 206 => "YH",
231 207 => "ZH",
232 208 => "AI",
233 209 => "BI",
234 210 => "CI",
235 211 => "DI",
236 212 => "EI",
237 213 => "FI",
238 214 => "GI",
239 215 => "HI",
240 216 => "II",
241 217 => "JI",
242 218 => "KI",
243 219 => "LI",
244 220 => "MI",
245 221 => "NI",
246 222 => "OI",
247 223 => "PI",
248 224 => "QI",
249 225 => "RI",
250 226 => "SI",
251 227 => "TI",
252 228 => "UI",
253 229 => "VI",
254 230 => "WI",
255 231 => "XI",
256 232 => "YI",
257 233 => "ZI",
258 234 => "AJ",
259 235 => "BJ",
260 236 => "CJ",
261 237 => "DJ",
262 238 => "EJ",
263 239 => "FJ",
264 240 => "GJ",
265 241 => "HJ",
266 242 => "IJ",
267 243 => "JJ",
268 244 => "KJ",
269 245 => "LJ",
270 246 => "MJ",
271 247 => "NJ",
272 248 => "OJ",
273 249 => "PJ",
274 250 => "QJ",
275 251 => "RJ",
276 252 => "SJ",
277 253 => "TJ",
278 254 => "UJ",
279 255 => "VJ",
280 };
281 output.push_str(code);
282 }
283 return output;
284 }
285
286 pub fn get(&self) -> String {
288 let code = self.get_slim();
289 format!(
290 "{}-{}-{}-{}",
291 &code[0..4],
292 &code[4..8],
293 &code[8..12],
294 &code[12..16]
295 )
296 }
297
298 pub fn new_from(code: String) -> Result<Self, IllegalIDString> {
301 beep();
302
303 let code = code.trim().to_string();
304 let code = code.replace("-", "").replace("_", "");
305
306 if code.len() != mem::size_of::<NumberType>() * 2 {
307 return Err(IllegalIDString(code));
308 }
309
310 let mut output: NumberType = 0;
311
312 for i in 0..mem::size_of::<NumberType>() {
313 let chunk = format!(
314 "{}{}",
315 code.chars().nth(i * 2).unwrap(),
316 code.chars().nth(i * 2 + 1).unwrap()
317 );
318
319 let num = match chunk.as_str() {
321 "AA" => 0,
322 "BA" => 1,
323 "CA" => 2,
324 "DA" => 3,
325 "EA" => 4,
326 "FA" => 5,
327 "GA" => 6,
328 "HA" => 7,
329 "IA" => 8,
330 "JA" => 9,
331 "KA" => 10,
332 "LA" => 11,
333 "MA" => 12,
334 "NA" => 13,
335 "OA" => 14,
336 "PA" => 15,
337 "QA" => 16,
338 "RA" => 17,
339 "SA" => 18,
340 "TA" => 19,
341 "UA" => 20,
342 "VA" => 21,
343 "WA" => 22,
344 "XA" => 23,
345 "YA" => 24,
346 "ZA" => 25,
347 "AB" => 26,
348 "BB" => 27,
349 "CB" => 28,
350 "DB" => 29,
351 "EB" => 30,
352 "FB" => 31,
353 "GB" => 32,
354 "HB" => 33,
355 "IB" => 34,
356 "JB" => 35,
357 "KB" => 36,
358 "LB" => 37,
359 "MB" => 38,
360 "NB" => 39,
361 "OB" => 40,
362 "PB" => 41,
363 "QB" => 42,
364 "RB" => 43,
365 "SB" => 44,
366 "TB" => 45,
367 "UB" => 46,
368 "VB" => 47,
369 "WB" => 48,
370 "XB" => 49,
371 "YB" => 50,
372 "ZB" => 51,
373 "AC" => 52,
374 "BC" => 53,
375 "CC" => 54,
376 "DC" => 55,
377 "EC" => 56,
378 "FC" => 57,
379 "GC" => 58,
380 "HC" => 59,
381 "IC" => 60,
382 "JC" => 61,
383 "KC" => 62,
384 "LC" => 63,
385 "MC" => 64,
386 "NC" => 65,
387 "OC" => 66,
388 "PC" => 67,
389 "QC" => 68,
390 "RC" => 69,
391 "SC" => 70,
392 "TC" => 71,
393 "UC" => 72,
394 "VC" => 73,
395 "WC" => 74,
396 "XC" => 75,
397 "YC" => 76,
398 "ZC" => 77,
399 "AD" => 78,
400 "BD" => 79,
401 "CD" => 80,
402 "DD" => 81,
403 "ED" => 82,
404 "FD" => 83,
405 "GD" => 84,
406 "HD" => 85,
407 "ID" => 86,
408 "JD" => 87,
409 "KD" => 88,
410 "LD" => 89,
411 "MD" => 90,
412 "ND" => 91,
413 "OD" => 92,
414 "PD" => 93,
415 "QD" => 94,
416 "RD" => 95,
417 "SD" => 96,
418 "TD" => 97,
419 "UD" => 98,
420 "VD" => 99,
421 "WD" => 100,
422 "XD" => 101,
423 "YD" => 102,
424 "ZD" => 103,
425 "AE" => 104,
426 "BE" => 105,
427 "CE" => 106,
428 "DE" => 107,
429 "EE" => 108,
430 "FE" => 109,
431 "GE" => 110,
432 "HE" => 111,
433 "IE" => 112,
434 "JE" => 113,
435 "KE" => 114,
436 "LE" => 115,
437 "ME" => 116,
438 "NE" => 117,
439 "OE" => 118,
440 "PE" => 119,
441 "QE" => 120,
442 "RE" => 121,
443 "SE" => 122,
444 "TE" => 123,
445 "UE" => 124,
446 "VE" => 125,
447 "WE" => 126,
448 "XE" => 127,
449 "YE" => 128,
450 "ZE" => 129,
451 "AF" => 130,
452 "BF" => 131,
453 "CF" => 132,
454 "DF" => 133,
455 "EF" => 134,
456 "FF" => 135,
457 "GF" => 136,
458 "HF" => 137,
459 "IF" => 138,
460 "JF" => 139,
461 "KF" => 140,
462 "LF" => 141,
463 "MF" => 142,
464 "NF" => 143,
465 "OF" => 144,
466 "PF" => 145,
467 "QF" => 146,
468 "RF" => 147,
469 "SF" => 148,
470 "TF" => 149,
471 "UF" => 150,
472 "VF" => 151,
473 "WF" => 152,
474 "XF" => 153,
475 "YF" => 154,
476 "ZF" => 155,
477 "AG" => 156,
478 "BG" => 157,
479 "CG" => 158,
480 "DG" => 159,
481 "EG" => 160,
482 "FG" => 161,
483 "GG" => 162,
484 "HG" => 163,
485 "IG" => 164,
486 "JG" => 165,
487 "KG" => 166,
488 "LG" => 167,
489 "MG" => 168,
490 "NG" => 169,
491 "OG" => 170,
492 "PG" => 171,
493 "QG" => 172,
494 "RG" => 173,
495 "SG" => 174,
496 "TG" => 175,
497 "UG" => 176,
498 "VG" => 177,
499 "WG" => 178,
500 "XG" => 179,
501 "YG" => 180,
502 "ZG" => 181,
503 "AH" => 182,
504 "BH" => 183,
505 "CH" => 184,
506 "DH" => 185,
507 "EH" => 186,
508 "FH" => 187,
509 "GH" => 188,
510 "HH" => 189,
511 "IH" => 190,
512 "JH" => 191,
513 "KH" => 192,
514 "LH" => 193,
515 "MH" => 194,
516 "NH" => 195,
517 "OH" => 196,
518 "PH" => 197,
519 "QH" => 198,
520 "RH" => 199,
521 "SH" => 200,
522 "TH" => 201,
523 "UH" => 202,
524 "VH" => 203,
525 "WH" => 204,
526 "XH" => 205,
527 "YH" => 206,
528 "ZH" => 207,
529 "AI" => 208,
530 "BI" => 209,
531 "CI" => 210,
532 "DI" => 211,
533 "EI" => 212,
534 "FI" => 213,
535 "GI" => 214,
536 "HI" => 215,
537 "II" => 216,
538 "JI" => 217,
539 "KI" => 218,
540 "LI" => 219,
541 "MI" => 220,
542 "NI" => 221,
543 "OI" => 222,
544 "PI" => 223,
545 "QI" => 224,
546 "RI" => 225,
547 "SI" => 226,
548 "TI" => 227,
549 "UI" => 228,
550 "VI" => 229,
551 "WI" => 230,
552 "XI" => 231,
553 "YI" => 232,
554 "ZI" => 233,
555 "AJ" => 234,
556 "BJ" => 235,
557 "CJ" => 236,
558 "DJ" => 237,
559 "EJ" => 238,
560 "FJ" => 239,
561 "GJ" => 240,
562 "HJ" => 241,
563 "IJ" => 242,
564 "JJ" => 243,
565 "KJ" => 244,
566 "LJ" => 245,
567 "MJ" => 246,
568 "NJ" => 247,
569 "OJ" => 248,
570 "PJ" => 249,
571 "QJ" => 250,
572 "RJ" => 251,
573 "SJ" => 252,
574 "TJ" => 253,
575 "UJ" => 254,
576 "VJ" => 255,
577 _ => {
578 return Err(IllegalIDString(code));
579 }
580 } as NumberType;
581
582 output |= num << (i * 8);
583 }
584
585 Ok(Self(output))
586 }
587
588 pub fn generate() -> Self {
590 beep();
591 Self(rand::rng().random())
592 }
593}
594
595#[cfg(feature = "serde")]
596impl serde::Serialize for EvilID {
597 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
598 where
599 S: serde::Serializer,
600 {
601 if serializer.is_human_readable() {
602 serializer.serialize_str(&self.codify())
603 } else {
604 serializer.serialize_u64(self.0)
605 }
606 }
607}
608
609#[cfg(feature = "serde")]
610impl<'de> serde::Deserialize<'de> for EvilID {
611 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
612 where
613 D: serde::Deserializer<'de>,
614 {
615 use serde::de::Visitor;
616
617 struct IDVisitor;
618
619 impl<'de> Visitor<'de> for IDVisitor {
620 type Value = EvilID;
621
622 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
623 formatter.write_str("A u64 number or proper id string is required.")
624 }
625
626 fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
627 where
628 E: serde::de::Error,
629 {
630 Ok(EvilID(v))
631 }
632
633 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
634 where
635 E: serde::de::Error,
636 {
637 EvilID::uncodify(v.to_string()).map_err(serde::de::Error::custom)
638 }
639 }
640
641 deserializer.deserialize_any(IDVisitor)
642 }
643}
644
645impl Debug for EvilID {
646 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
647 f.debug_tuple("ID").field(&self.get()).finish()
648 }
649}
650
651impl Display for EvilID {
652 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
653 write!(f, "{}", self.get())
654 }
655}
656
657impl Default for EvilID {
658 fn default() -> Self {
659 Self::generate()
660 }
661}
662
663fn beep() {
665 #[cfg(feature = "beep")]
666 println!("Beep");
667}
668
669mod error {
670 use std::{error::Error, fmt::Display};
671
672 #[derive(Debug)]
673 pub struct IllegalIDString(pub String);
675
676 impl Error for IllegalIDString {}
677
678 impl Display for IllegalIDString {
679 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
680 write!(f, "Unable to convert {} into a valid id.", self.0)
681 }
682 }
683}
684
685