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 => "MS",
25 1 => "TP",
26 2 => "XJ",
27 3 => "ZU",
28 4 => "AW",
29 5 => "HL",
30 6 => "LT",
31 7 => "UT",
32 8 => "OJ",
33 9 => "MI",
34 10 => "TW",
35 11 => "QQ",
36 12 => "BN",
37 13 => "SL",
38 14 => "JN",
39 15 => "LG",
40 16 => "PJ",
41 17 => "LH",
42 18 => "MA",
43 19 => "WB",
44 20 => "CZ",
45 21 => "VJ",
46 22 => "NO",
47 23 => "MP",
48 24 => "HP",
49 25 => "KX",
50 26 => "UL",
51 27 => "JZ",
52 28 => "CI",
53 29 => "TR",
54 30 => "FP",
55 31 => "OT",
56 32 => "NN",
57 33 => "IQ",
58 34 => "NS",
59 35 => "SV",
60 36 => "JC",
61 37 => "ME",
62 38 => "FE",
63 39 => "MK",
64 40 => "SK",
65 41 => "IK",
66 42 => "WM",
67 43 => "SD",
68 44 => "QC",
69 45 => "MD",
70 46 => "CL",
71 47 => "DN",
72 48 => "CE",
73 49 => "KO",
74 50 => "LI",
75 51 => "BB",
76 52 => "AD",
77 53 => "FS",
78 54 => "OD",
79 55 => "SC",
80 56 => "RC",
81 57 => "NY",
82 58 => "JV",
83 59 => "GI",
84 60 => "VG",
85 61 => "HG",
86 62 => "HT",
87 63 => "HB",
88 64 => "MO",
89 65 => "NF",
90 66 => "BE",
91 67 => "HY",
92 68 => "IY",
93 69 => "NG",
94 70 => "BR",
95 71 => "UX",
96 72 => "ES",
97 73 => "SP",
98 74 => "RB",
99 75 => "PU",
100 76 => "GT",
101 77 => "OW",
102 78 => "QH",
103 79 => "HV",
104 80 => "LL",
105 81 => "PC",
106 82 => "ZS",
107 83 => "IX",
108 84 => "OQ",
109 85 => "WO",
110 86 => "EI",
111 87 => "TH",
112 88 => "XL",
113 89 => "PV",
114 90 => "WJ",
115 91 => "MU",
116 92 => "DY",
117 93 => "YA",
118 94 => "XT",
119 95 => "UR",
120 96 => "PX",
121 97 => "FF",
122 98 => "CU",
123 99 => "UM",
124 100 => "KL",
125 101 => "BU",
126 102 => "AC",
127 103 => "AI",
128 104 => "HE",
129 105 => "YG",
130 106 => "UQ",
131 107 => "IA",
132 108 => "IH",
133 109 => "OU",
134 110 => "OS",
135 111 => "XD",
136 112 => "UH",
137 113 => "KV",
138 114 => "DP",
139 115 => "GH",
140 116 => "AZ",
141 117 => "DI",
142 118 => "HH",
143 119 => "TM",
144 120 => "BC",
145 121 => "SQ",
146 122 => "IC",
147 123 => "EB",
148 124 => "QO",
149 125 => "NR",
150 126 => "CC",
151 127 => "ZH",
152 128 => "DV",
153 129 => "TT",
154 130 => "FU",
155 131 => "LU",
156 132 => "PB",
157 133 => "RK",
158 134 => "VV",
159 135 => "CB",
160 136 => "AJ",
161 137 => "CN",
162 138 => "UY",
163 139 => "LJ",
164 140 => "DZ",
165 141 => "KG",
166 142 => "FT",
167 143 => "JD",
168 144 => "GZ",
169 145 => "MZ",
170 146 => "EC",
171 147 => "GN",
172 148 => "QD",
173 149 => "BT",
174 150 => "SW",
175 151 => "WF",
176 152 => "UG",
177 153 => "EP",
178 154 => "EU",
179 155 => "AL",
180 156 => "SR",
181 157 => "NH",
182 158 => "VW",
183 159 => "SX",
184 160 => "WU",
185 161 => "CW",
186 162 => "TS",
187 163 => "XU",
188 164 => "ET",
189 165 => "XS",
190 166 => "IL",
191 167 => "JU",
192 168 => "SZ",
193 169 => "EE",
194 170 => "BO",
195 171 => "GL",
196 172 => "YC",
197 173 => "QP",
198 174 => "JL",
199 175 => "GY",
200 176 => "VB",
201 177 => "GC",
202 178 => "XV",
203 179 => "LV",
204 180 => "KK",
205 181 => "ZB",
206 182 => "HK",
207 183 => "EZ",
208 184 => "CS",
209 185 => "IJ",
210 186 => "ZO",
211 187 => "GJ",
212 188 => "ZJ",
213 189 => "PT",
214 190 => "GG",
215 191 => "PL",
216 192 => "NB",
217 193 => "XB",
218 194 => "XI",
219 195 => "KC",
220 196 => "UK",
221 197 => "JE",
222 198 => "LO",
223 199 => "LF",
224 200 => "XQ",
225 201 => "OX",
226 202 => "XW",
227 203 => "SY",
228 204 => "DT",
229 205 => "TZ",
230 206 => "MC",
231 207 => "AM",
232 208 => "AG",
233 209 => "VH",
234 210 => "DW",
235 211 => "YV",
236 212 => "GW",
237 213 => "MF",
238 214 => "WK",
239 215 => "LS",
240 216 => "WW",
241 217 => "FJ",
242 218 => "RG",
243 219 => "SE",
244 220 => "MW",
245 221 => "WP",
246 222 => "IT",
247 223 => "IM",
248 224 => "YI",
249 225 => "KY",
250 226 => "XP",
251 227 => "IG",
252 228 => "RW",
253 229 => "YE",
254 230 => "VC",
255 231 => "UA",
256 232 => "ZL",
257 233 => "II",
258 234 => "CD",
259 235 => "CY",
260 236 => "DQ",
261 237 => "UW",
262 238 => "MH",
263 239 => "XZ",
264 240 => "ZV",
265 241 => "ND",
266 242 => "BF",
267 243 => "GO",
268 244 => "SN",
269 245 => "HN",
270 246 => "MX",
271 247 => "BM",
272 248 => "UI",
273 249 => "CX",
274 250 => "MG",
275 251 => "FZ",
276 252 => "VM",
277 253 => "XR",
278 254 => "NW",
279 255 => "OE",
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("_", "").to_uppercase();
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 "MS" => 0,
322 "TP" => 1,
323 "XJ" => 2,
324 "ZU" => 3,
325 "AW" => 4,
326 "HL" => 5,
327 "LT" => 6,
328 "UT" => 7,
329 "OJ" => 8,
330 "MI" => 9,
331 "TW" => 10,
332 "QQ" => 11,
333 "BN" => 12,
334 "SL" => 13,
335 "JN" => 14,
336 "LG" => 15,
337 "PJ" => 16,
338 "LH" => 17,
339 "MA" => 18,
340 "WB" => 19,
341 "CZ" => 20,
342 "VJ" => 21,
343 "NO" => 22,
344 "MP" => 23,
345 "HP" => 24,
346 "KX" => 25,
347 "UL" => 26,
348 "JZ" => 27,
349 "CI" => 28,
350 "TR" => 29,
351 "FP" => 30,
352 "OT" => 31,
353 "NN" => 32,
354 "IQ" => 33,
355 "NS" => 34,
356 "SV" => 35,
357 "JC" => 36,
358 "ME" => 37,
359 "FE" => 38,
360 "MK" => 39,
361 "SK" => 40,
362 "IK" => 41,
363 "WM" => 42,
364 "SD" => 43,
365 "QC" => 44,
366 "MD" => 45,
367 "CL" => 46,
368 "DN" => 47,
369 "CE" => 48,
370 "KO" => 49,
371 "LI" => 50,
372 "BB" => 51,
373 "AD" => 52,
374 "FS" => 53,
375 "OD" => 54,
376 "SC" => 55,
377 "RC" => 56,
378 "NY" => 57,
379 "JV" => 58,
380 "GI" => 59,
381 "VG" => 60,
382 "HG" => 61,
383 "HT" => 62,
384 "HB" => 63,
385 "MO" => 64,
386 "NF" => 65,
387 "BE" => 66,
388 "HY" => 67,
389 "IY" => 68,
390 "NG" => 69,
391 "BR" => 70,
392 "UX" => 71,
393 "ES" => 72,
394 "SP" => 73,
395 "RB" => 74,
396 "PU" => 75,
397 "GT" => 76,
398 "OW" => 77,
399 "QH" => 78,
400 "HV" => 79,
401 "LL" => 80,
402 "PC" => 81,
403 "ZS" => 82,
404 "IX" => 83,
405 "OQ" => 84,
406 "WO" => 85,
407 "EI" => 86,
408 "TH" => 87,
409 "XL" => 88,
410 "PV" => 89,
411 "WJ" => 90,
412 "MU" => 91,
413 "DY" => 92,
414 "YA" => 93,
415 "XT" => 94,
416 "UR" => 95,
417 "PX" => 96,
418 "FF" => 97,
419 "CU" => 98,
420 "UM" => 99,
421 "KL" => 100,
422 "BU" => 101,
423 "AC" => 102,
424 "AI" => 103,
425 "HE" => 104,
426 "YG" => 105,
427 "UQ" => 106,
428 "IA" => 107,
429 "IH" => 108,
430 "OU" => 109,
431 "OS" => 110,
432 "XD" => 111,
433 "UH" => 112,
434 "KV" => 113,
435 "DP" => 114,
436 "GH" => 115,
437 "AZ" => 116,
438 "DI" => 117,
439 "HH" => 118,
440 "TM" => 119,
441 "BC" => 120,
442 "SQ" => 121,
443 "IC" => 122,
444 "EB" => 123,
445 "QO" => 124,
446 "NR" => 125,
447 "CC" => 126,
448 "ZH" => 127,
449 "DV" => 128,
450 "TT" => 129,
451 "FU" => 130,
452 "LU" => 131,
453 "PB" => 132,
454 "RK" => 133,
455 "VV" => 134,
456 "CB" => 135,
457 "AJ" => 136,
458 "CN" => 137,
459 "UY" => 138,
460 "LJ" => 139,
461 "DZ" => 140,
462 "KG" => 141,
463 "FT" => 142,
464 "JD" => 143,
465 "GZ" => 144,
466 "MZ" => 145,
467 "EC" => 146,
468 "GN" => 147,
469 "QD" => 148,
470 "BT" => 149,
471 "SW" => 150,
472 "WF" => 151,
473 "UG" => 152,
474 "EP" => 153,
475 "EU" => 154,
476 "AL" => 155,
477 "SR" => 156,
478 "NH" => 157,
479 "VW" => 158,
480 "SX" => 159,
481 "WU" => 160,
482 "CW" => 161,
483 "TS" => 162,
484 "XU" => 163,
485 "ET" => 164,
486 "XS" => 165,
487 "IL" => 166,
488 "JU" => 167,
489 "SZ" => 168,
490 "EE" => 169,
491 "BO" => 170,
492 "GL" => 171,
493 "YC" => 172,
494 "QP" => 173,
495 "JL" => 174,
496 "GY" => 175,
497 "VB" => 176,
498 "GC" => 177,
499 "XV" => 178,
500 "LV" => 179,
501 "KK" => 180,
502 "ZB" => 181,
503 "HK" => 182,
504 "EZ" => 183,
505 "CS" => 184,
506 "IJ" => 185,
507 "ZO" => 186,
508 "GJ" => 187,
509 "ZJ" => 188,
510 "PT" => 189,
511 "GG" => 190,
512 "PL" => 191,
513 "NB" => 192,
514 "XB" => 193,
515 "XI" => 194,
516 "KC" => 195,
517 "UK" => 196,
518 "JE" => 197,
519 "LO" => 198,
520 "LF" => 199,
521 "XQ" => 200,
522 "OX" => 201,
523 "XW" => 202,
524 "SY" => 203,
525 "DT" => 204,
526 "TZ" => 205,
527 "MC" => 206,
528 "AM" => 207,
529 "AG" => 208,
530 "VH" => 209,
531 "DW" => 210,
532 "YV" => 211,
533 "GW" => 212,
534 "MF" => 213,
535 "WK" => 214,
536 "LS" => 215,
537 "WW" => 216,
538 "FJ" => 217,
539 "RG" => 218,
540 "SE" => 219,
541 "MW" => 220,
542 "WP" => 221,
543 "IT" => 222,
544 "IM" => 223,
545 "YI" => 224,
546 "KY" => 225,
547 "XP" => 226,
548 "IG" => 227,
549 "RW" => 228,
550 "YE" => 229,
551 "VC" => 230,
552 "UA" => 231,
553 "ZL" => 232,
554 "II" => 233,
555 "CD" => 234,
556 "CY" => 235,
557 "DQ" => 236,
558 "UW" => 237,
559 "MH" => 238,
560 "XZ" => 239,
561 "ZV" => 240,
562 "ND" => 241,
563 "BF" => 242,
564 "GO" => 243,
565 "SN" => 244,
566 "HN" => 245,
567 "MX" => 246,
568 "BM" => 247,
569 "UI" => 248,
570 "CX" => 249,
571 "MG" => 250,
572 "FZ" => 251,
573 "VM" => 252,
574 "XR" => 253,
575 "NW" => 254,
576 "OE" => 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