#[cfg(feature = "analysis")]
use crate::analysis::BoardValue;
#[cfg(feature = "game")]
use crate::game::GameStatus;
#[cfg(feature = "analysis")]
use crate::prelude::Board;
use crate::prelude::{Action, Color, Dove};
#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error("BoardError::{0}")]
BoardError(#[from] BoardError),
#[cfg(feature = "game")]
#[error("GameError::{0}")]
GameError(#[from] GameError),
#[cfg(feature = "analysis")]
#[error("AnalysisError::{0}")]
AnalysisError(#[from] AnalysisError),
}
impl Error {
pub fn as_board_error(&self) -> Option<&BoardError> {
match self {
Error::BoardError(err) => Some(err),
#[cfg(any(feature = "game", feature = "analysis"))]
_ => None,
}
}
#[cfg(feature = "game")]
pub fn as_game_error(&self) -> Option<&GameError> {
match self {
Error::GameError(err) => Some(err),
_ => None,
}
}
#[cfg(feature = "analysis")]
pub fn as_analysis_error(&self) -> Option<&AnalysisError> {
match self {
Error::AnalysisError(err) => Some(err),
_ => None,
}
}
}
#[derive(Debug, thiserror::Error)]
pub enum BoardError {
#[error("BoardCreateError::{kind}")]
BoardCreateError { kind: BoardCreateErrorKind },
#[error("ActionPeformError::{kind:?}")]
ActionPerformError {
kind: ActionPerformErrorKind,
action: Action,
},
#[error("InternalError")]
InternalError,
#[error("ActionConvertError::{0}")]
ActionConvertError(#[from] ActionConvertError),
}
impl BoardError {
pub fn as_action_convert_error(&self) -> Option<&ActionConvertError> {
match self {
BoardError::ActionConvertError(err) => Some(err),
_ => None,
}
}
}
#[derive(Debug)]
pub enum BoardCreateErrorKind {
BossNotFound(Color),
DoveDuplicated(Color, Dove),
PositionDuplicated,
DoveIsolated,
PositionOutOfRange,
BitNeitherSingleNorZero([[u64; 6]; 2], u64),
}
impl std::fmt::Display for BoardCreateErrorKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
use BoardCreateErrorKind::*;
let msg = match self {
BossNotFound(color) => format!("BossNotFound: {color} boss not found"),
DoveDuplicated(color, dove) => {
format!("DoveDuplicated: found duplicated doves ({color}, {dove:?})")
}
PositionDuplicated => {
"PositionDuplicated: position duplicated with another dove".to_string()
}
DoveIsolated => "DoveIsolated: some dove is isolated".to_string(),
PositionOutOfRange => "PositionOutOfRange: some dove is out of 4x4 region".to_string(),
BitNeitherSingleNorZero(pos, bit) => {
format!("BitNeitherSingleNorZero: position {bit} in {pos:?} is neither single bit nor zero")
}
};
write!(f, "{msg}")
}
}
impl From<BoardCreateErrorKind> for Error {
fn from(value: BoardCreateErrorKind) -> Self {
BoardError::BoardCreateError { kind: value }.into()
}
}
#[derive(Debug)]
pub enum ActionPerformErrorKind {
ToBeIsolated, OutOfField, InvalidShift, InvalidPosition,
AlreadyOnBoard,
ObstacleInRoute,
ThroughOuterField,
TriedToRemoveBoss,
NotOnBoard,
}
impl From<(ActionPerformErrorKind, Action)> for Error {
fn from((kind, action): (ActionPerformErrorKind, Action)) -> Self {
BoardError::ActionPerformError { kind, action }.into()
}
}
#[derive(Debug, thiserror::Error)]
pub enum ActionConvertError {
#[error("EncodingError::{kind:?}")]
EncodingError { kind: EncodingErrorKind },
#[error("DecodingError::{kind:?}")]
DecodingError { kind: DecodingErrorKind },
}
#[derive(Debug)]
pub enum EncodingErrorKind {
BossNotFound(Color),
DoveNotFound(Color, Dove),
}
impl From<EncodingErrorKind> for Error {
fn from(value: EncodingErrorKind) -> Self {
let err = ActionConvertError::EncodingError { kind: value };
Error::from(BoardError::from(err))
}
}
#[derive(Debug)]
pub enum DecodingErrorKind {
NumberNotFollowAfterNEWS,
UnexpectedCharacter(char),
ColorNotInferred,
DoveNotInferred,
BossNotFound(Color),
DoveNotOnBoard(Color, Dove),
}
impl From<DecodingErrorKind> for Error {
fn from(value: DecodingErrorKind) -> Self {
let err = ActionConvertError::DecodingError { kind: value };
Error::from(BoardError::from(err))
}
}
#[cfg(feature = "game")]
#[derive(Debug, thiserror::Error)]
pub enum GameError {
#[error("GameRuleCreateError::{kind:?}")]
GameRuleCreateError { kind: GameRuleCreateErrorKind },
#[error("PlayingError::{kind:?}")]
PlayingError { kind: PlayingErrorKind },
}
#[cfg(feature = "game")]
#[derive(Debug)]
pub enum GameRuleCreateErrorKind {
InitialBoardError,
}
#[cfg(feature = "game")]
impl From<GameRuleCreateErrorKind> for Error {
fn from(value: GameRuleCreateErrorKind) -> Self {
GameError::GameRuleCreateError { kind: value }.into()
}
}
#[cfg(feature = "game")]
#[derive(Debug)]
pub enum PlayingErrorKind {
PlayerMismatch,
ProhibitedRemove(Action),
GameFinished(GameStatus),
}
#[cfg(feature = "game")]
impl From<PlayingErrorKind> for Error {
fn from(value: PlayingErrorKind) -> Self {
GameError::PlayingError { kind: value }.into()
}
}
#[cfg(feature = "analysis")]
#[derive(Debug, thiserror::Error)]
pub enum AnalysisError {
#[error("ArgsValidationError::{kind}")]
ArgsValidationError { kind: ArgsValidationErrorKind },
#[error("BoardValueMismatch: value of board is {0:?} than value in argument")]
BoardValueMismatch(std::cmp::Ordering),
}
#[cfg(feature = "analysis")]
#[derive(Debug)]
pub enum ArgsValidationErrorKind {
FinishedGameBoard(Board),
UnsupportedValue(BoardValue),
DrawJudge,
}
#[cfg(feature = "analysis")]
impl From<ArgsValidationErrorKind> for Error {
fn from(value: ArgsValidationErrorKind) -> Self {
AnalysisError::ArgsValidationError { kind: value }.into()
}
}
#[cfg(feature = "analysis")]
impl std::fmt::Display for ArgsValidationErrorKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
use ArgsValidationErrorKind::*;
let msg = match self {
FinishedGameBoard(_board) => String::from("FinishedGameBoard: board of finished game"),
UnsupportedValue(value) => format!("UnsupportedValue: {value} not supported"),
DrawJudge => String::from("DrawJudge: Judge::Draw not supported"),
};
write!(f, "{msg}")
}
}
#[derive(Debug, Clone, Copy, thiserror::Error)]
pub(crate) enum DirectionError {
#[error("bit out of field: {0}")]
BitOutOfField(u64),
#[error("index out of range: {0}")]
IndexOutOfRange(usize),
}