evil_id/
lib.rs

1use std::fmt::{Debug, Display};
2use std::mem;
3
4use rand::Rng;
5
6use error::IllegalIDString;
7
8type NumberType = u64;
9
10/// Simply stores a u64 and allows it to be exported in a human readable format.
11#[derive(Clone, Copy, PartialEq, Eq, Hash)]
12pub struct EvilID(NumberType);
13
14impl EvilID {
15    /// Get a basic version of the id string without any dashes.
16    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            // How else am I supposed to be able to call it an evil id!?
23            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    /// Get the id string.
287    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    /// Get an id from an id string.
299    /// Any `-` are removed before proccesing the string.
300    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            // What? You thought that I was going to stop being evil?!
320            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    /// Generate a new id.
589    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
663/// This isn't evil! Beep is just da best word ever!
664fn beep() {
665    #[cfg(feature = "beep")]
666    println!("Beep");
667}
668
669mod error {
670    use std::{error::Error, fmt::Display};
671
672    #[derive(Debug)]
673    /// If you are getting this error you either have an illegal pair of characters or the string is the wrong length.
674    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// Beep