monorepo/sgf/src/lib.rs

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,
},
)])
}
*/