extern crate board_game_traits;
use board_game_traits::{GameResult, Position};
use std::error;
use std::fmt;
#[derive(Clone, Copy, Eq, PartialEq, Debug, PartialOrd, Ord)]
pub enum ErrorKind {
ParseError,
AmbiguousMove,
IllegalMove,
IllegalPosition,
IoError,
Other,
}
#[derive(Debug)]
pub struct Error {
kind: ErrorKind,
error: Box<dyn error::Error + Send + Sync>,
source: Option<Box<dyn error::Error + Send + Sync>>,
}
impl Error {
pub fn new<E>(kind: ErrorKind, error: E) -> Error
where
E: Into<Box<dyn error::Error + Send + Sync>>,
{
Error {
kind,
error: error.into(),
source: None,
}
}
pub fn new_caused_by<E, F>(kind: ErrorKind, error: E, source: F) -> Error
where
E: Into<Box<dyn error::Error + Send + Sync>>,
F: Into<Box<dyn error::Error + Send + Sync>>,
{
Error {
kind,
error: error.into(),
source: Some(source.into()),
}
}
pub fn new_parse_error<E>(error: E) -> Error
where
E: Into<Box<dyn error::Error + Send + Sync>>,
{
Error {
kind: ErrorKind::ParseError,
error: error.into(),
source: None,
}
}
}
impl error::Error for Error {}
impl fmt::Display for Error {
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
match self.kind {
ErrorKind::ParseError => write!(fmt, "Parse error. "),
ErrorKind::AmbiguousMove => write!(fmt, "Ambiguous move. "),
ErrorKind::IllegalMove => write!(fmt, "Illegal move. "),
ErrorKind::IllegalPosition => write!(fmt, "Illegal position. "),
ErrorKind::IoError => write!(fmt, "IO error. "),
ErrorKind::Other => Ok(()),
}?;
write!(fmt, "{}", self.error)?;
if let Some(ref source) = self.source {
write!(fmt, "\nCaused by: {}", source)?;
}
Ok(())
}
}
pub trait PgnPosition: Sized + Position + PartialEq {
const REQUIRED_TAGS: &'static [(&'static str, &'static str)];
const POSSIBLE_GAME_RESULTS: &'static [(&'static str, Option<GameResult>)] = &[
("*", None),
("1-0", Some(GameResult::WhiteWin)),
("0-1", Some(GameResult::BlackWin)),
("1/2-1/2", Some(GameResult::Draw)),
];
#[inline]
fn pgn_game_result(&self) -> Option<&'static str> {
self.game_result().map(|game_result| match game_result {
GameResult::WhiteWin => "1-0",
GameResult::BlackWin => "0-1",
GameResult::Draw => "1/2-1/2",
})
}
const POSSIBLE_MOVE_ANNOTATIONS: &'static [&'static str] = &["!!", "!?", "?!", "??", "!", "?"];
#[inline]
fn from_fen(fen: &str) -> Result<Self, Error> {
Self::from_fen_with_settings(fen, &Self::Settings::default())
}
fn from_fen_with_settings(fen: &str, settings: &Self::Settings) -> Result<Self, Error>;
fn to_fen(&self) -> String;
fn move_from_san(&self, input: &str) -> Result<Self::Move, Error>;
fn move_to_san(&self, mv: &Self::Move) -> String;
fn move_from_lan(&self, input: &str) -> Result<Self::Move, Error>;
fn move_to_lan(&self, mv: &Self::Move) -> String;
}