Crate pgn_reader[−][src]
A fast non-allocating reader for chess games in PGN notation.
Reader
parses games and calls methods of a user provided Visitor
.
Implementing custom visitors allows for maximum flexibility:
- The reader itself does not allocate. The visitor can decide if and how to represent games in memory.
- The reader does not validate move legality. This allows implementing support for custom chess variants, or delaying move validation.
- The visitor can signal to the reader that it does not care about a game or variation.
Flow
Visitor methods are called in this order:
Examples
A visitor that counts the number of syntactically valid moves in mainline of each game.
extern crate pgn_reader; use pgn_reader::{Visitor, Skip, Reader, San}; struct MoveCounter { moves: usize, } impl MoveCounter { fn new() -> MoveCounter { MoveCounter { moves: 0 } } } impl<'pgn> Visitor<'pgn> for MoveCounter { type Result = usize; fn begin_game(&mut self) { self.moves = 0; } fn san(&mut self, _san: San) { self.moves += 1; } fn begin_variation(&mut self) -> Skip { Skip(true) // stay in the mainline } fn end_game(&mut self, _game: &'pgn [u8]) -> Self::Result { self.moves } } fn main() { let pgn = b"1. e4 e5 2. Nf3 (2. f4) { game paused due to bad weather } 2... Nf6 *"; let mut counter = MoveCounter::new(); let reader = Reader::new(&mut counter, pgn); let moves: usize = reader.into_iter().sum(); assert_eq!(moves, 4); }
A visitor that returns the final position using Shakmaty.
extern crate pgn_reader; extern crate shakmaty; use pgn_reader::{Visitor, Skip, Reader, San}; use shakmaty::{Chess, Position}; use shakmaty::fen::Fen; struct LastPosition { pos: Chess, } impl LastPosition { fn new() -> LastPosition { LastPosition { pos: Chess::default() } } } impl<'pgn> Visitor<'pgn> for LastPosition { type Result = Chess; fn header(&mut self, key: &'pgn [u8], value: &'pgn [u8]) { // Support games from a non-standard starting position. if key == b"FEN" { let pos = Fen::from_ascii(value).ok() .and_then(|f| f.position().ok()); if let Some(pos) = pos { self.pos = pos; } } } fn begin_variation(&mut self) -> Skip { Skip(true) // stay in the mainline } fn san(&mut self, san: San) { if let Ok(m) = san.to_move(&self.pos) { self.pos.play_unchecked(&m); } } fn end_game(&mut self, _game: &'pgn [u8]) -> Self::Result { ::std::mem::replace(&mut self.pos, Chess::default()) } } fn main() { let pgn = b"1. f3 e5 2. g4 Qh4#"; let mut visitor = LastPosition::new(); let mut reader = Reader::new(&mut visitor, pgn); let pos = reader.read_game(); assert!(pos.map_or(false, |p| p.is_checkmate())); }
Structs
InvalidNag |
Error when parsing an invalid NAG. |
Iter |
View a |
Nag |
A numeric annotation glyph like |
Reader |
Reads a PGN. |
Skip |
Tell the reader to skip over a game or variation. |
Enums
CastlingSide |
|
Color |
|
Outcome |
Outcome of a game. |
Role |
Piece types: |
San |
A move in Standard Algebraic Notation. |
Square |
A square index. |
Traits
Visitor |
Consumes games from a reader. |