check_buddy_pgn_parser/
lib.rs

1use anyhow::{anyhow, Result};
2use check_buddy::*;
3
4pub struct PgnParser;
5
6impl PgnParser {
7    pub fn parse(buffer: String) -> Result<Game> {
8        let mut game = Game::default();
9
10        #[cfg(target_family = "unix")]
11        let empty_line = "\n\n";
12        #[cfg(target_family = "windows")]
13        let empty_line = "\r\n\r\n";
14
15        let (info, uci) = buffer
16            .split_once::<&str>(empty_line)
17            .ok_or(anyhow!("Can't split info and UCI"))?;
18
19        Self::parse_info(&mut game, info)?;
20        Self::parse_uci(&mut game, uci)?;
21
22        Ok(game)
23    }
24
25    fn parse_info(game: &mut Game, info: &str) -> Result<()> {
26        info.lines()
27            .map(|line| {
28                let mut chars = line.chars();
29                chars.next();
30                chars.next_back();
31                chars.as_str()
32            })
33            .for_each(|line| {
34                let (title, content) = line.split_once(' ').expect("Couldn't parse info row");
35                let content = content.trim_matches('\"');
36                game.info.insert(title.to_string(), content.to_string());
37            });
38        Ok(())
39    }
40
41    fn parse_uci(game: &mut Game, uci: &str) -> Result<()> {
42        let binding = uci.split_whitespace().collect::<Vec<&str>>();
43        let mut uci_line = binding.chunks(3).collect::<Vec<&[&str]>>();
44        let _winning = uci_line.pop();
45
46        for moves in uci_line.iter() {
47            let (move1, move2) = (moves[1], moves[2]);
48
49            let uci_move1 = game.board_map.parse_uci_to_move(move1)?;
50            game.board_map.uci_move_turn(uci_move1)?;
51            let uci_move2 = game.board_map.parse_uci_to_move(move2)?;
52            game.board_map.uci_move_turn(uci_move2)?;
53        }
54
55        Ok(())
56    }
57}
58
59#[cfg(test)]
60mod tests {
61    use super::*;
62
63    fn get_example_pgn() -> Vec<u8> {
64        let mut path = std::env::current_dir().unwrap();
65        #[cfg(target_family = "unix")]
66        path.push("assets/pgns/example.pgn");
67        #[cfg(target_family = "windows")]
68        path.push("assets\\pgns\\example.pgn");
69
70        std::fs::read(path).unwrap()
71    }
72
73    #[test]
74    fn should_return_happy_flow() {
75        let pgn = String::from_utf8(get_example_pgn()).unwrap();
76        let _ = PgnParser::parse(pgn).unwrap();
77    }
78}