mod date; pub use date::Date; pub mod go; mod tree; use tree::parse_collection; use thiserror::Error; #[derive(Debug)] pub enum Error { InvalidField, InvalidBoardSize, Incomplete, InvalidSgf(VerboseNomError), } #[derive(Debug)] pub struct VerboseNomError(nom::error::VerboseError); impl From> 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>> for Error { fn from(err: nom::Err>) -> 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), } impl From> for ParseError { fn from(err: nom::error::Error<&str>) -> Self { Self::NomError(nom::error::Error { input: err.input.to_owned(), code: err.code.clone(), }) } } pub enum Game { Go(go::Game), Unsupported(tree::Tree), } pub fn parse_sgf(input: &str) -> Result, Error> { let (_, trees) = parse_collection::>(input)?; Ok(trees .into_iter() .map(|t| match t.sequence[0].find_prop("GM") { Some(prop) if prop.values == vec!["1".to_owned()] => { Game::Go(go::Game::try_from(t).expect("properly structured game tree")) } _ => Game::Unsupported(t), }) .collect::>()) } /* impl From<(&str, VerboseErrorKind)> for impl From> for ParseError { fn from(err: nom::error::VerboseError<&str>) -> Self { Self::NomErrors( err.errors .into_iter() .map(|err| ParseError::from(err)) .collect(), ) /* Self::NomError(nom::error::Error { input: err.input.to_owned(), code: err.code.clone(), }) */ } } */