#![allow(dead_code)] /// Manage UCI messages and link into chess component pub mod uci_engine { use itertools::join; mod chess_move { pub struct Move {} } mod chess_info{ pub struct Info {} } mod chess_option{ pub struct Opt{} } pub struct UciEngine { name: String, author: String, } impl UciEngine { pub fn new(name: &str, author: &str) -> UciEngine { UciEngine{name: name.to_string(), author: author.to_string()} } pub fn name(&self) -> String { self.name.clone() } pub fn author(&self) -> String { self.author.clone() } pub fn update(&mut self, id: &Id){ match &id.name { Some(name) => self.name = name.clone(), None => {} } match &id.author { Some(author) => self.author = author.clone(), None => {} } } } pub struct Id {name: Option, author: Option} impl Id { pub fn new(name: Option<&str>, author: Option<&str>) -> Id { Id{ name: if let Some(name) = name {Some(name.to_string())} else {None}, author: if let Some(author) = author {Some(author.to_string())} else {None} } } pub fn update(&mut self, name: Option<&str>, author: Option<&str>){ match &name { Some(name) => self.name = Some(name.to_string()), None => {} } match &author { Some(author) => self.author = Some(author.to_string()), None => {} } } } pub enum UciCommand { Id{id: Id}, UciOk, ReadyOk, BestMove{best_move: chess_move::Move, ponder: chess_move::Move}, CopyProtection, // unimplemented Registration, // unimplemented Info{infos: Vec}, Opt{options: Vec}, } /// Parse UCI commands /// /// * id /// * name *x* /// /// this must be sent after receiving the "uci" command to identify the engine, /// e.g. "id name Shredder X.Y\n" /// * author *x* /// /// this must be sent after receiving the "uci" command to identify the engine, /// e.g. "id author Stefan MK\n" /// /// ```rust /// use chess_uci::uci_engine::{parse, UciCommand, Id, UciEngine}; /// let mut engine = UciEngine::new("Test", "Bat"); /// /// engine.exec(&parse(&mut "id name Baptiste".to_string()).expect("simple id name command")); /// assert_eq!(engine.name(), "Baptiste"); /// /// engine.exec(&parse(&mut "id author Monique Jouve".to_string()).expect("simple id author command")); /// assert_eq!(engine.author(), "Monique Jouve"); /// /// ``` pub fn parse(message: &mut String) -> Result { let mut message_iter = message.split_whitespace(); match message_iter.next() { None => Err("No command provided"), Some("id") => match message_iter.collect::>().as_slice() { [] => Err("Empty id command"), ["name"] => Err("Empty id name command"), ["author"] => Err("Empty id author command"), ["name", tail @ ..] => Ok(UciCommand::Id{id: Id::new(Some(&join(tail, " ")), None)}), ["author", tail @ ..] => Ok(UciCommand::Id{id: Id::new(None, Some(&join(tail, " ")))}), _ => Err("Invalid id subcommand") }, Some("uciok") => unimplemented!(), Some("readyok") => unimplemented!(), Some("bestmove") => unimplemented!(), Some("copyprotection") => unimplemented!(), Some("registration") => unimplemented!(), Some("info") => unimplemented!(), Some("option") => unimplemented!(), Some(_) => Err("Unknown command provided"), } } impl UciEngine { pub fn exec(&mut self, command: &UciCommand){ match command { UciCommand::Id{id} => self.update(&id), _ => unimplemented!(), } } } } #[cfg(test)] mod tests { use super::uci_engine::*; #[test] fn new_uci() { let mut engine = UciEngine::new("Test", "Bat"); assert_eq!(engine.name(), "Test"); assert_eq!(engine.author(), "Bat"); let new_id = Id::new(Some("Test 1"), None); engine.update(&new_id); assert_eq!(engine.name(), "Test 1"); assert_eq!(engine.author(), "Bat"); let new_id = Id::new(Some("Test 2"), Some("Bat 1")); engine.update(&new_id); assert_eq!(engine.name(), "Test 2"); assert_eq!(engine.author(), "Bat 1"); } }