use yap::Tokens; use crate::parsing::{parse_n, parse_number}; use super::model::TargetArea; pub fn parse_target_area(tokens: &mut impl Tokens) -> Option { tokens.optional(|t| { if !t.tokens("target area: x=".chars()) { return None; } let x = parse_bounds(t)?; if !t.tokens(", y=".chars()) { return None; } let y = parse_bounds(t)?; Some(TargetArea(x, y)) }) } pub fn parse_bounds(tokens: &mut impl Tokens) -> Option<(isize, isize)> { tokens.optional(|t| { let numbers: Option<[isize; 2]> = parse_n(t, |t| parse_number(t), |t| t.tokens("..".chars())); numbers.map(|numbers| (numbers[0], numbers[1])) }) } #[cfg(test)] mod test { use yap::IntoTokens; use crate::day_17::model::TargetArea; const EXAMPLE: &str = "target area: x=20..30, y=-10..-5"; #[test] fn parse_example() { let example = super::parse_target_area(&mut EXAMPLE.into_tokens()); assert_eq!(example, Some(TargetArea((20, 30), (-10, -5)))); } }