check_buddy_pgn_parser/
lib.rs1use 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}