117 lines
3.0 KiB
Rust
117 lines
3.0 KiB
Rust
mod date;
|
|
|
|
mod game;
|
|
pub use game::{GameNode, GameRecord, GameTree, MoveNode, Player};
|
|
|
|
mod parser;
|
|
pub use parser::{parse_collection, Move, Size};
|
|
|
|
mod types;
|
|
pub use types::*;
|
|
|
|
pub use date::Date;
|
|
|
|
use std::{fs::File, io::Read};
|
|
use thiserror::Error;
|
|
|
|
#[derive(Debug)]
|
|
pub enum Error {
|
|
InvalidField,
|
|
InvalidBoardSize,
|
|
Incomplete,
|
|
InvalidSgf(VerboseNomError),
|
|
}
|
|
|
|
#[allow(dead_code)]
|
|
#[derive(Debug)]
|
|
pub struct VerboseNomError(nom::error::VerboseError<String>);
|
|
|
|
impl From<nom::error::VerboseError<&str>> for VerboseNomError {
|
|
fn from(err: nom::error::VerboseError<&str>) -> Self {
|
|
VerboseNomError(nom::error::VerboseError {
|
|
errors: err
|
|
.errors
|
|
.into_iter()
|
|
.map(|err| (err.0.to_owned(), err.1))
|
|
.collect(),
|
|
})
|
|
}
|
|
}
|
|
|
|
impl From<nom::Err<nom::error::VerboseError<&str>>> for Error {
|
|
fn from(err: nom::Err<nom::error::VerboseError<&str>>) -> Self {
|
|
match err {
|
|
nom::Err::Incomplete(_) => Error::Incomplete,
|
|
nom::Err::Error(e) => Error::InvalidSgf(VerboseNomError::from(e)),
|
|
nom::Err::Failure(e) => Error::InvalidSgf(VerboseNomError::from(e)),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, PartialEq, Error)]
|
|
pub enum ParseError {
|
|
#[error("An unknown error was found")]
|
|
NomError(nom::error::Error<String>),
|
|
}
|
|
|
|
impl From<nom::error::Error<&str>> for ParseError {
|
|
fn from(err: nom::error::Error<&str>) -> Self {
|
|
Self::NomError(nom::error::Error {
|
|
input: err.input.to_owned(),
|
|
code: err.code,
|
|
})
|
|
}
|
|
}
|
|
|
|
/// Given raw text of an SGF file, parse all of the games within that file.
|
|
///
|
|
/// The outermost Result is for any errors that happen in opening and reading the file, or if hte
|
|
/// outermost part of the file format is invalid.
|
|
///
|
|
/// The inner Result is for errors in each individual game in the file. All of the other games can
|
|
/// still be kept as valid.
|
|
pub fn parse_sgf(input: &str) -> Result<Vec<Result<GameRecord, game::GameError>>, Error> {
|
|
let (_, games) = parse_collection::<nom::error::VerboseError<&str>>(input)?;
|
|
let games = games
|
|
.into_iter()
|
|
.map(GameRecord::try_from)
|
|
.collect::<Vec<Result<GameRecord, game::GameError>>>();
|
|
|
|
Ok(games)
|
|
}
|
|
|
|
/// Given a path, parse all of the games stored in that file.
|
|
///
|
|
/// See also `parse_sgf`
|
|
pub fn parse_sgf_file(
|
|
path: &std::path::Path,
|
|
) -> Result<Vec<Result<GameRecord, game::GameError>>, Error> {
|
|
let mut file = File::open(path).unwrap();
|
|
let mut text = String::new();
|
|
let _ = file.read_to_string(&mut text);
|
|
|
|
parse_sgf(&text)
|
|
}
|
|
|
|
/*
|
|
pub fn parse_sgf(_input: &str) -> Result<Vec<Game>, Error> {
|
|
Ok(vec![Game::new(
|
|
GameType::Go,
|
|
Size {
|
|
width: 19,
|
|
height: 19,
|
|
},
|
|
Player {
|
|
name: None,
|
|
rank: None,
|
|
team: None,
|
|
},
|
|
Player {
|
|
name: None,
|
|
rank: None,
|
|
team: None,
|
|
},
|
|
)])
|
|
}
|
|
*/
|