use std::error::Error;
use std::fmt::{Display, Formatter};
use std::num::ParseIntError;
use crate::sokoban_plus::BoxID;
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub(super) enum SokobanPlusInputKind {
Boxorder,
Goalorder,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum SokobanPlusSyntaxErrorKind {
ParseIntError,
TooManyPlusIDs,
}
#[derive(Debug, Clone, PartialEq, Eq)]
struct ErrorPayload {
pos: usize,
input_kind: SokobanPlusInputKind,
kind: SokobanPlusSyntaxErrorKind,
source: Option<ParseIntError>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SokobanPlusSyntaxError(Box<ErrorPayload>);
impl SokobanPlusSyntaxError {
pub(super) fn new(
pos: usize, input_kind: SokobanPlusInputKind, kind: SokobanPlusSyntaxErrorKind,
source: Option<ParseIntError>,
) -> Self {
Self(Box::new(ErrorPayload {
pos,
input_kind,
kind,
source,
}))
}
pub fn kind(&self) -> SokobanPlusSyntaxErrorKind { self.0.kind }
}
impl Display for SokobanPlusSyntaxError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let input_kind_s = match self.0.input_kind {
SokobanPlusInputKind::Boxorder => "boxorder",
SokobanPlusInputKind::Goalorder => "goalorder",
};
match self.0.kind {
SokobanPlusSyntaxErrorKind::ParseIntError => {
write!(
f,
"failed parsing Sokoban+ IDs from {} at {}",
input_kind_s, self.0.pos
)
}
SokobanPlusSyntaxErrorKind::TooManyPlusIDs => {
write!(
f,
"Sokoban+ {} can't assign more Sokoban+ IDs than maximum allowed number of {} ({})",
input_kind_s,
match self.0.input_kind {
SokobanPlusInputKind::Boxorder => "boxes",
SokobanPlusInputKind::Goalorder => "goals",
},
BoxID::MAX
)
}
}
}
}
impl Error for SokobanPlusSyntaxError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
match &self.0.source {
Some(ref_box_dyn) => Some(ref_box_dyn),
None => None,
}
}
}