use array_init::try_array_init;
use crate::ParseFailure;
use substring::Substring;
#[derive(Debug, PartialEq, Eq)]
pub struct GearItem {
pub id: u16,
pub main: u8,
pub subs: [u8; 3],
}
impl std::fmt::Display for GearItem {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{:x}",
u64::from_str_radix(
&format!(
"{:05b}{:05b}{:05b}{:05b}{:05b}",
self.id, self.main, self.subs[0], self.subs[1], self.subs[2]
),
2
)
.unwrap()
)
}
}
macro_rules! assign_or_fail {
($e:expr, $fail:expr) => {
if let Ok(v) = { $e } {
v
} else {
$fail
}
};
}
impl std::str::FromStr for GearItem {
type Err = ParseFailure;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let id = assign_or_fail!(
u16::from_str_radix(s.substring(0, 2), 16),
return Err(ParseFailure::Value)
);
let s = if let Some(v) = crate::hexstr_to_bin(s.substring(2, 7)) {
v
} else {
return Err(ParseFailure::Value);
};
let main = assign_or_fail!(
u8::from_str_radix(s.substring(0, 5), 2),
return Err(ParseFailure::Value)
);
let step = [5, 10, 15, 20];
let subs: [u8; 3] = assign_or_fail!(
try_array_init(|i| { u8::from_str_radix(s.substring(step[i], step[i + 1]), 2) }),
return Err(ParseFailure::Value)
);
Ok(Self { id, main, subs })
}
}