Expand description
A fast non-allocating and streaming reader for chess games in PGN notation.
BufferedReader
parses games and calls methods of a user provided
Visitor
. Implementing custom visitors allows for maximum flexibility:
- The reader itself does not allocate (besides a single fixed-size buffer). 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.
use std::io;
use pgn_reader::{Visitor, Skip, BufferedReader, SanPlus};
struct MoveCounter {
moves: usize,
}
impl MoveCounter {
fn new() -> MoveCounter {
MoveCounter { moves: 0 }
}
}
impl Visitor for MoveCounter {
type Result = usize;
fn begin_game(&mut self) {
self.moves = 0;
}
fn san(&mut self, _san_plus: SanPlus) {
self.moves += 1;
}
fn begin_variation(&mut self) -> Skip {
Skip(true) // stay in the mainline
}
fn end_game(&mut self) -> Self::Result {
self.moves
}
}
fn main() -> io::Result<()> {
let pgn = b"1. e4 e5 2. Nf3 (2. f4)
{ game paused due to bad weather }
2... Nf6 *";
let mut reader = BufferedReader::new_cursor(&pgn[..]);
let mut counter = MoveCounter::new();
let moves = reader.read_game(&mut counter)?;
assert_eq!(moves, Some(4));
Ok(())
}
A visitor that returns the final position using Shakmaty.
use std::io;
use shakmaty::{CastlingMode, Chess, Position};
use shakmaty::fen::Fen;
use pgn_reader::{Visitor, Skip, RawHeader, BufferedReader, SanPlus};
struct LastPosition {
pos: Chess,
}
impl LastPosition {
fn new() -> LastPosition {
LastPosition { pos: Chess::default() }
}
}
impl Visitor for LastPosition {
type Result = Chess;
fn header(&mut self, key: &[u8], value: RawHeader<'_>) {
// Support games from a non-standard starting position.
if key == b"FEN" {
let pos = Fen::from_ascii(value.as_bytes()).ok()
.and_then(|f| f.into_position(CastlingMode::Standard).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_plus: SanPlus) {
if let Ok(m) = san_plus.san.to_move(&self.pos) {
self.pos.play_unchecked(&m);
}
}
fn end_game(&mut self) -> Self::Result {
::std::mem::replace(&mut self.pos, Chess::default())
}
}
fn main() -> io::Result<()> {
let pgn = b"1. f3 e5 2. g4 Qh4#";
let mut reader = BufferedReader::new_cursor(&pgn[..]);
let mut visitor = LastPosition::new();
let pos = reader.read_game(&mut visitor)?;
assert!(pos.map_or(false, |p| p.is_checkmate()));
Ok(())
}
Structs§
- Buffered
Reader - A buffered PGN reader.
- Into
Iter - Iterator returned by
BufferedReader::into_iter()
. - Nag
- A numeric annotation glyph like
?
,!!
or$42
. - RawComment
- A comment, excluding the braces.
- RawHeader
- A header value.
- SanPlus
- A
San
and possible check and checkmate suffixes. - Skip
- Tell the reader to skip over a game or variation.
Enums§
- Castling
Side KingSide
(O-O) orQueenSide
(O-O-O).- Color
White
orBlack
.- File
- A file of the chessboard.
- Outcome
- Outcome of a game.
- Rank
- A rank of the chessboard.
- Role
- Piece types:
Pawn
,Knight
,Bishop
,Rook
,Queen
,King
. - San
- A move in Standard Algebraic Notation.
- Square
- A square of the chessboard.
Traits§
- Visitor
- Consumes games from a reader.