use std::fmt;
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct Weight(u16);
impl Weight {
pub const MAX: Weight = Weight(1000);
pub const fn new(weight: u16) -> Self {
Self(weight)
}
pub fn parse(representation: &str) -> Option<Self> {
const MAX: u16 = 1000;
let mut chars = representation.trim().chars();
match chars.next() {
Some('q' | 'Q') => (),
_ => return None,
};
match chars.next() {
Some('=') => (),
_ => return None,
};
let mut value = match chars.next() {
Some('0') => 0,
Some('1') => MAX,
_ => return None,
};
match chars.next() {
Some('.') => {}
None => return Some(Self(value)),
_ => return None,
};
let mut factor = 100;
loop {
match chars.next() {
Some(n @ '0'..='9') => {
if factor < 1 {
return None;
}
value += factor * (n as u16 - '0' as u16);
}
None => {
return if value <= MAX { Some(Self(value)) } else { None };
}
_ => return None,
};
factor /= 10;
}
}
}
impl fmt::Display for Weight {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
match self.0 {
1000 => fmt::Display::fmt("q=1", formatter),
0 => fmt::Display::fmt("q=0", formatter),
mut weight => {
if weight % 100 == 0 {
weight /= 100;
} else if weight % 10 == 0 {
weight /= 10;
}
write!(formatter, "q=0.{}", weight)
}
}
}
}