mod raw_gui_message;
use raw_gui_message::RawGuiMessage;
dry_mods::mods! {
pub mod use go, register, set_option, set_position;
}
use crate::define_message_enum::define_message_enum;
use crate::{MessageParseError, MessageTryFromRawMessageError};
use std::fmt::{Debug, Display, Formatter};
use std::str::FromStr;
define_message_enum! {
enum GuiMessage {
%["uci"]
UseUci,
%["debug"]
Debug(%bool),
%["isready"]
IsReady,
%["setoption"]
%%[parameters = [(Name, "name"), (Value, "value")]]
SetOption(%SetOptionMessage),
%["register"]
%%[parameters = [(Name, "name"), (Code, "code")]]
Register(%RegisterMessageKind),
%["ucinewgame"]
UciNewGame,
%["position"]
%%[parameters = [(Fen, "fen"), (Moves, "moves")]]
SetPosition(%SetPositionMessageKind),
%["go"]
%%[parameters = [(SearchMoves, "searchmoves"), **(Ponder, "ponder"), (WhiteTime, "wtime"), (BlackTime, "btime"), (WhiteIncrement, "winc"), (BlackIncrement, "binc"), (MovesToGo, "movestogo"), (Depth, "depth"), (Nodes, "nodes"), (Mate, "mate"), (MoveTime, "movetime"), **(Infinite, "infinite")]]
Go(%GoMessage),
%["stop"]
Stop,
%["ponderhit"]
PonderHit,
%["quit"]
Quit
}
}
impl FromStr for GuiMessage {
type Err = MessageParseError<GuiMessageParameterPointer>;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let raw_message =
RawGuiMessage::from_str(s).map_err(MessageParseError::RawMessageParseError)?;
Self::try_from(raw_message).map_err(MessageParseError::MessageTryFromRawMessageError)
}
}
impl TryFrom<RawGuiMessage> for GuiMessage {
type Error = MessageTryFromRawMessageError<GuiMessageParameterPointer>;
#[allow(clippy::too_many_lines)]
fn try_from(raw_message: RawGuiMessage) -> Result<Self, Self::Error> {
match raw_message.message_pointer {
GuiMessagePointer::UseUci => Ok(Self::UseUci),
GuiMessagePointer::IsReady => Ok(Self::IsReady),
GuiMessagePointer::UciNewGame => Ok(Self::UciNewGame),
GuiMessagePointer::Stop => Ok(Self::Stop),
GuiMessagePointer::PonderHit => Ok(Self::PonderHit),
GuiMessagePointer::Quit => Ok(Self::Quit),
GuiMessagePointer::Debug => match raw_message
.value
.ok_or(Self::Error::MissingValue)?
.as_bytes()
{
b"on" => Ok(Self::Debug(true)),
b"off" => Ok(Self::Debug(false)),
_ => Err(Self::Error::ValueParseError),
},
GuiMessagePointer::SetOption => {
Ok(Self::SetOption(SetOptionMessage::try_from(raw_message)?))
}
GuiMessagePointer::Register => {
Ok(Self::Register(RegisterMessageKind::try_from(raw_message)?))
}
GuiMessagePointer::SetPosition => Ok(Self::SetPosition(
SetPositionMessageKind::try_from(raw_message)?,
)),
GuiMessagePointer::Go => Ok(Self::Go(GoMessage::try_from(raw_message)?)),
}
}
}
impl Display for GuiMessage {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Self::UseUci => f.write_str("uci\n"),
Self::Debug(value) => writeln!(f, "debug {}", if *value { "on" } else { "off" }),
Self::IsReady => f.write_str("isready\n"),
Self::SetOption(message) => f.write_str(&message.to_string()),
Self::Register(kind) => f.write_str(&kind.to_string()),
Self::UciNewGame => f.write_str("ucinewgame\n"),
Self::SetPosition(kind) => f.write_str(&kind.to_string()),
Self::Go(message) => f.write_str(&message.to_string()),
Self::Stop => f.write_str("stop\n"),
Self::PonderHit => f.write_str("ponderhit\n"),
Self::Quit => f.write_str("quit\n"),
}
}
}