use super::bingo::{Board, Field, Game}; use crate::parsing::{newline, parse_number, space}; use yap::{IntoTokens, Tokens}; pub fn parse_field(tokens: &mut impl Tokens) -> Option { parse_number(tokens).map(|number| Field { number, marked: false, }) } pub fn parse_field_line(tokens: &mut impl Tokens) -> Option<[Field; 5]> { tokens .sep_by(|t| parse_field(t), |t| space(t)) .collect::>() .try_into() .ok() } pub fn parse_field_line_array(tokens: &mut impl Tokens) -> Option<[[Field; 5]; 5]> { tokens .sep_by(|t| parse_field_line(t), |t| newline(t)) .collect::>() .try_into() .ok() } pub fn parse_board(tokens: &mut impl Tokens) -> Option { parse_field_line_array(tokens).map(|fields| Board { fields, finished: false, }) } pub fn parse_boards(tokens: &mut impl Tokens) -> Vec { tokens .sep_by(|t| parse_board(t), |t| newline(t) && newline(t)) .collect() } pub fn parse_input_numbers(tokens: &mut impl Tokens) -> Vec { tokens .sep_by(|t| parse_number(t), |t| t.token(',')) .collect() } pub fn parse_game(input: &str) -> Game { let mut tokens = input.into_tokens(); let input_numbers = parse_input_numbers(&mut tokens); tokens.skip_many(newline); let boards = parse_boards(&mut tokens); Game { input_numbers, boards, } } #[cfg(test)] mod test { use yap::IntoTokens; #[test] fn parse_input_numbers() { assert_eq!( vec![1, 2, 3], super::parse_input_numbers(&mut "1,2,3".into_tokens()) ) } #[test] fn parse_field_line() { if let Some(line) = super::parse_field_line(&mut " 3 15 0 2 22".into_tokens()) { assert_eq!(3, line[0].number); assert_eq!(15, line[1].number); assert_eq!(0, line[2].number); assert_eq!(2, line[3].number); assert_eq!(22, line[4].number); } } #[test] fn parse_board() { const BOARD: &str = " 3 15 0 2 22 9 18 13 17 5 19 8 7 25 23 20 11 10 24 4 14 21 16 12 6"; assert!(super::parse_board(&mut BOARD.into_tokens()).is_some()); } }