1extern crate array_init;
2extern crate substring;
3
4pub mod splat1;
5pub use splat1::S1Loadout;
6
7pub mod splat2;
8pub use splat2::S2Loadout;
9
10#[derive(Debug, PartialEq, Eq)]
16pub enum Loadout {
17 Splat1(S1Loadout),
18 Splat2(S2Loadout),
19}
20
21impl std::str::FromStr for Loadout {
22 type Err = ParseFailure;
23
24 fn from_str(s: &str) -> Result<Self, Self::Err> {
25 if let Some((prefix, code)) = s.split_once(':') {
26 match prefix {
27 "s1" => Ok(Self::Splat1(code.parse()?)),
28 "s2" => Ok(Self::Splat2(code.parse()?)),
29 _ => Err(ParseFailure::Prefix),
30 }
31 } else {
32 Err(ParseFailure::Value)
33 }
34 }
35}
36
37impl std::fmt::Display for Loadout {
38 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
39 match self {
40 Loadout::Splat1(s) => write!(f, "s1:{}", s),
41 Loadout::Splat2(s) => write!(f, "s2:{}", s),
42 }
43 }
44}
45
46#[derive(Debug)]
47pub enum ParseFailure {
48 Length,
49 Value,
50 Prefix,
51}
52
53fn hexstr_to_bin(s: &str) -> Option<String> {
54 let mut ret = String::new();
55 for c in s.chars() {
56 if let Some(c) = hexchar_to_bin(&c) {
57 ret.push_str(c);
58 } else {
59 return None;
60 }
61 }
62 Some(ret)
63}
64
65#[inline]
66fn hexchar_to_bin(c: &char) -> Option<&str> {
67 Some(match c {
68 '0' => "0000",
69 '1' => "0001",
70 '2' => "0010",
71 '3' => "0011",
72 '4' => "0100",
73 '5' => "0101",
74 '6' => "0110",
75 '7' => "0111",
76 '8' => "1000",
77 '9' => "1001",
78 'a' => "1010",
79 'b' => "1011",
80 'c' => "1100",
81 'd' => "1101",
82 'e' => "1110",
83 'f' => "1111",
84 'A' => "1010",
85 'B' => "1011",
86 'C' => "1100",
87 'D' => "1101",
88 'E' => "1110",
89 _ => return None,
90 })
91}