use std::{backtrace::Backtrace, error::Error, fmt, io};
use crate::{material::Material, types::Metric};
pub type SyzygyResult<T> = Result<T, SyzygyError>;
pub type ProbeResult<T> = Result<T, ProbeError>;
#[derive(Debug)]
pub enum SyzygyError {
Castling,
TooManyPieces,
MissingTable {
#[allow(missing_docs)]
metric: Metric,
#[allow(missing_docs)]
material: Material,
},
ProbeFailed {
#[allow(missing_docs)]
metric: Metric,
#[allow(missing_docs)]
material: Material,
#[allow(missing_docs)]
error: Box<ProbeError>,
},
}
impl fmt::Display for SyzygyError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
SyzygyError::Castling => write!(
f,
"syzygy tables do not contain position with castling rights"
),
SyzygyError::TooManyPieces => write!(f, "too many pieces"),
SyzygyError::MissingTable { metric, material } => {
write!(f, "required {metric} table not found: {material}")
}
SyzygyError::ProbeFailed {
metric,
material,
error,
} => write!(f, "failed to probe {metric} table {material}: {error}"),
}
}
}
impl Error for SyzygyError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
match self {
SyzygyError::ProbeFailed { error, .. } => Some(error),
_ => None,
}
}
}
#[derive(Debug)]
pub enum ProbeError {
Read {
#[allow(missing_docs)]
error: io::Error,
},
Magic {
#[allow(missing_docs)]
magic: [u8; 4],
},
CorruptedTable {
#[allow(missing_docs)]
backtrace: Backtrace,
},
}
impl fmt::Display for ProbeError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ProbeError::Read { error } => write!(f, "i/o error reading table file: {error}"),
ProbeError::Magic { magic } => write!(f, "invalid magic header bytes: {magic:x?}"),
ProbeError::CorruptedTable { backtrace } => write!(f, "corrupted table: {backtrace}"),
}
}
}
impl Error for ProbeError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
match self {
ProbeError::Read { error } => Some(error),
_ => None,
}
}
}
pub trait ProbeResultExt<T> {
fn ctx(self, metric: Metric, material: Material) -> SyzygyResult<T>;
}
impl<T> ProbeResultExt<T> for ProbeResult<T> {
fn ctx(self, metric: Metric, material: Material) -> SyzygyResult<T> {
self.map_err(|error| SyzygyError::ProbeFailed {
metric,
material: material.into_normalized(),
error: Box::new(error),
})
}
}
impl From<io::Error> for ProbeError {
fn from(error: io::Error) -> ProbeError {
match error.kind() {
io::ErrorKind::UnexpectedEof => ProbeError::CorruptedTable {
backtrace: Backtrace::capture(),
},
_ => ProbeError::Read { error },
}
}
}
macro_rules! throw {
() => {
return Err(crate::errors::ProbeError::CorruptedTable {
backtrace: ::std::backtrace::Backtrace::capture(),
})
};
}
macro_rules! u {
($e:expr) => {
match $e {
Some(ok) => ok,
None => throw!(),
}
};
}
macro_rules! ensure {
($cond:expr) => {
if !$cond {
throw!();
}
};
}