use std::convert::TryInto;
use super::scanner::Scanner;
use crate::feature::Charge;
pub fn read_charge(scanner: &mut Scanner) -> Option<Charge> {
match scanner.peek() {
Some('+') => {
scanner.pop();
match fifteen(scanner) {
Some(value) => Some(value.try_into().expect("charge")),
None => match scanner.peek() {
Some('+') => {
scanner.pop();
Some(Charge::Two)
}
_ => Some(Charge::One),
},
}
}
Some('-') => {
scanner.pop();
match fifteen(scanner) {
Some(value) => Some((-value).try_into().expect("charge")),
None => match scanner.peek() {
Some('-') => {
scanner.pop();
Some(Charge::MinusTwo)
}
_ => Some(Charge::MinusOne),
},
}
}
_ => None,
}
}
fn fifteen(scanner: &mut Scanner) -> Option<i8> {
match scanner.peek() {
Some('1'..='9') => Some(match scanner.pop() {
Some('1') => match scanner.peek() {
Some('1'..='5') => match scanner.pop() {
Some('1') => 11,
Some('2') => 12,
Some('3') => 13,
Some('4') => 14,
Some('5') => 15,
_ => 1,
},
_ => 1,
},
Some('2') => 2,
Some('3') => 3,
Some('4') => 4,
Some('5') => 5,
Some('6') => 6,
Some('7') => 7,
Some('8') => 8,
Some('9') => 9,
_ => unreachable!("fifteen"),
}),
_ => None,
}
}
#[cfg(test)]
mod tests {
use super::*;
use pretty_assertions::assert_eq;
#[test]
fn none() {
let mut scanner = Scanner::new("X");
assert_eq!(read_charge(&mut scanner), None)
}
#[test]
fn minus_x() {
let mut scanner = Scanner::new("-X");
assert_eq!(read_charge(&mut scanner), Some(Charge::MinusOne))
}
#[test]
fn minus_2_x() {
let mut scanner = Scanner::new("-1X");
assert_eq!(read_charge(&mut scanner), Some(Charge::MinusOne))
}
#[test]
fn minus_minus_x() {
let mut scanner = Scanner::new("--X");
assert_eq!(read_charge(&mut scanner), Some(Charge::MinusTwo))
}
#[test]
fn minus_15_x() {
let mut scanner = Scanner::new("-15X");
assert_eq!(read_charge(&mut scanner), Some(Charge::MinusFifteen))
}
#[test]
fn plus_x() {
let mut scanner = Scanner::new("+X");
assert_eq!(read_charge(&mut scanner), Some(Charge::One))
}
#[test]
fn plus_plus_x() {
let mut scanner = Scanner::new("++X");
assert_eq!(read_charge(&mut scanner), Some(Charge::Two))
}
#[test]
fn plus_2_x() {
let mut scanner = Scanner::new("+2X");
assert_eq!(read_charge(&mut scanner), Some(Charge::Two))
}
#[test]
fn plus_15_x() {
let mut scanner = Scanner::new("+15X");
assert_eq!(read_charge(&mut scanner), Some(Charge::Fifteen))
}
}