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 => "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    /// 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("_", "");
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                "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    /// 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