#chess #pgn

pgn-reader

Fast non-allocating reader for chess games in PGN notation

8 breaking releases

0.9.0 Jul 29, 2018
0.7.0 Jun 5, 2018
0.5.0 Mar 15, 2018
0.3.0 Nov 4, 2017

#6 in Games

Download history 7/week @ 2018-05-24 39/week @ 2018-05-31 17/week @ 2018-06-07 59/week @ 2018-06-14 10/week @ 2018-06-21 89/week @ 2018-06-28 28/week @ 2018-07-05 10/week @ 2018-07-12 42/week @ 2018-07-19 2/week @ 2018-07-26 45/week @ 2018-08-02 99/week @ 2018-08-09 22/week @ 2018-08-16

126 downloads per month

GPL-3.0+

64KB
455 lines

pgn-reader

A fast non-allocating reader for chess games in PGN notation, as a Rust library.

Build Status crates.io docs.rs

Introduction

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.

Example

A visitor that counts the number of syntactically valid moves in the 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);
}

Documentation

Read the documentation

Benchmarks

Run with lichess_db_standard_rated_2014-07.pgn (1,048,440 games, 1000 MB uncompressed) on an SSD, Intel i7-5500U CPU @ 2.40GHz.

Benchmark Time Throughput
examples/stats.rs 4.0s 249.4 MB/s
examples/validate.rs 10.2s 98.0 MB/s
examples/parallel_validate.rs 4.5s 222.2 MB/s
examples/lichess4545.rs 1.6s 625.0 MB/s
scoutfish make 10.9s 96.1 MB/s
grep -F "[Event " -c 1.1s 909.1 MB/s

License

pgn-reader is licensed under the GPL-3.0 (or any later version at your option). See the COPYING file for the full license text.

Dependencies

~1MB
~15K SLoC