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)),
];
fn from_fen(fen: &str) -> 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;
}