use crate::hexstr_to_bin;
use crate::ParseFailure;
use substring::Substring;
#[derive(Debug, PartialEq, Eq)]
pub struct S1Loadout {
wepid: u8,
abilities: [u8; 12],
}
impl std::fmt::Display for S1Loadout {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut out = format!("{:02x}", self.wepid);
let mut astr = String::new();
for ability in &self.abilities {
astr.push_str(&format!("{:05b}", ability));
}
out.push_str(&format!("{:x}", u64::from_str_radix(&astr, 2).unwrap()));
f.write_str(out.trim_end_matches('0'))
}
}
impl std::str::FromStr for S1Loadout {
type Err = ParseFailure;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut code = s.to_string();
if code.len() > 17 {
return Err(ParseFailure::Length);
}
while code.len() < 17 {
code += "0";
}
let wepid = if let Ok(s) = u8::from_str_radix(code.substring(0, 2), 16) {
s
} else {
return Err(ParseFailure::Value);
};
let raw_abilities = if let Some(s) = hexstr_to_bin(code.substring(2, code.len())) {
s
} else {
return Err(ParseFailure::Value);
};
let mut abilities = [0; 12];
for i in (0..raw_abilities.len()).step_by(5) {
abilities[i / 5] =
if let Ok(s) = u8::from_str_radix(&raw_abilities.substring(i, i + 5), 2) {
s
} else {
return Err(ParseFailure::Value);
};
}
Ok(S1Loadout { wepid, abilities })
}
}
#[cfg(test)]
mod check {
use crate::*;
#[test]
fn s1_decode() {
assert_eq!(
S1Loadout {
wepid: 66,
abilities: [21, 21, 21, 12, 12, 12, 22, 22, 22, 16, 16, 16]
},
"42ad6ac632d6b421".parse().unwrap()
);
}
#[test]
fn s1_encode() {
assert_eq!(
S1Loadout {
wepid: 66,
abilities: [21, 21, 21, 12, 12, 12, 22, 22, 22, 16, 16, 16]
}
.to_string(),
"42ad6ac632d6b421"
);
}
}