Server and client communicates through unix socket
This commit is contained in:
parent
fcc5d5727a
commit
ae632df144
19
src/bin/client.rs
Normal file
19
src/bin/client.rs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
use std::io;
|
||||||
|
use std::os::unix::net::UnixStream;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let mut stream = match UnixStream::connect("/tmp/clichess.socket") {
|
||||||
|
Ok(sock) => sock,
|
||||||
|
Err(_) => {
|
||||||
|
println!("clichess daemon is not running.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let mut buffer = String::new();
|
||||||
|
let input = clichess::read_from_stream(&stream);
|
||||||
|
println!("{}", input);
|
||||||
|
io::stdin().read_line(&mut buffer).unwrap();
|
||||||
|
clichess::write_to_stream(&mut stream, String::from(buffer.trim()));
|
||||||
|
let response = clichess::read_from_stream(&stream);
|
||||||
|
println!("{}", response);
|
||||||
|
}
|
64
src/bin/server.rs
Normal file
64
src/bin/server.rs
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
use clichess;
|
||||||
|
use shakmaty::{Chess, Color};
|
||||||
|
use std::fs;
|
||||||
|
use std::io::prelude::*;
|
||||||
|
use std::os::unix::net::{UnixListener, UnixStream};
|
||||||
|
use std::str;
|
||||||
|
use std::sync::{Arc, Mutex};
|
||||||
|
use std::thread;
|
||||||
|
|
||||||
|
struct Server {
|
||||||
|
id: usize,
|
||||||
|
chess_position: Arc<Mutex<Chess>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let chess = Arc::new(Mutex::new(Chess::default()));
|
||||||
|
let mut counter = 0;
|
||||||
|
fs::remove_file("/tmp/clichess.socket");
|
||||||
|
|
||||||
|
let listener = UnixListener::bind("/tmp/clichess.socket").unwrap();
|
||||||
|
|
||||||
|
// accept connections and process them, spawning a new thread for each one
|
||||||
|
for stream in listener.incoming() {
|
||||||
|
match stream {
|
||||||
|
Ok(stream) => {
|
||||||
|
let chess = Arc::clone(&chess);
|
||||||
|
/* connection succeeded */
|
||||||
|
let server = Server {
|
||||||
|
id: counter,
|
||||||
|
chess_position: chess,
|
||||||
|
};
|
||||||
|
thread::spawn(|| handle_client(stream, server));
|
||||||
|
counter += 1;
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
println!("Could not create a connection: {}", err);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_client(mut stream: UnixStream, server: Server) {
|
||||||
|
{
|
||||||
|
let chess = server.chess_position.lock().unwrap();
|
||||||
|
clichess::write_to_stream(
|
||||||
|
&mut stream,
|
||||||
|
clichess::board_representation(&chess, Color::White),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
//let go of the lock while waiting for user input.
|
||||||
|
let input = clichess::read_from_stream(&stream);
|
||||||
|
{
|
||||||
|
let mut chess = server.chess_position.lock().unwrap();
|
||||||
|
match clichess::try_to_play_move(&chess, input) {
|
||||||
|
Ok(played_chess) => *chess = played_chess,
|
||||||
|
Err(e) => println!("Error: {}", e),
|
||||||
|
};
|
||||||
|
clichess::write_to_stream(
|
||||||
|
&mut stream,
|
||||||
|
clichess::board_representation(&chess, Color::White),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -1,222 +0,0 @@
|
|||||||
use colored::Colorize;
|
|
||||||
use shakmaty::fen;
|
|
||||||
use shakmaty::fen::Fen;
|
|
||||||
use shakmaty::fen::ParseFenError;
|
|
||||||
use shakmaty::san::ParseSanError;
|
|
||||||
use shakmaty::san::San;
|
|
||||||
use shakmaty::san::SanError;
|
|
||||||
use shakmaty::{Chess, Color, IllegalMoveError, Position, PositionError, Setup, Square};
|
|
||||||
use std::fmt;
|
|
||||||
use std::fs::File;
|
|
||||||
use std::io;
|
|
||||||
use std::io::{ErrorKind, Read, Write};
|
|
||||||
|
|
||||||
struct SquareToPrint {
|
|
||||||
color: String,
|
|
||||||
background_color: String,
|
|
||||||
square_representation: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum MoveInputError {
|
|
||||||
SanSanError(SanError),
|
|
||||||
SanParseSanError(ParseSanError),
|
|
||||||
ShakmatyIllegalMoveError(IllegalMoveError),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<SanError> for MoveInputError {
|
|
||||||
fn from(error: SanError) -> Self {
|
|
||||||
MoveInputError::SanSanError(error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<ParseSanError> for MoveInputError {
|
|
||||||
fn from(error: ParseSanError) -> Self {
|
|
||||||
MoveInputError::SanParseSanError(error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<IllegalMoveError> for MoveInputError {
|
|
||||||
fn from(error: IllegalMoveError) -> Self {
|
|
||||||
MoveInputError::ShakmatyIllegalMoveError(error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for MoveInputError {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
match self {
|
|
||||||
MoveInputError::SanSanError(san_error) => san_error.fmt(f),
|
|
||||||
MoveInputError::SanParseSanError(parse_san_error) => parse_san_error.fmt(f),
|
|
||||||
MoveInputError::ShakmatyIllegalMoveError(illegal_move_error) => {
|
|
||||||
illegal_move_error.fmt(f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum ReadingFileError {
|
|
||||||
ReadParseFenError(ParseFenError),
|
|
||||||
ReadFileError(io::Error),
|
|
||||||
ReadPositionError(PositionError),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<ParseFenError> for ReadingFileError {
|
|
||||||
fn from(error: ParseFenError) -> Self {
|
|
||||||
ReadingFileError::ReadParseFenError(error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<io::Error> for ReadingFileError {
|
|
||||||
fn from(error: io::Error) -> Self {
|
|
||||||
ReadingFileError::ReadFileError(error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<PositionError> for ReadingFileError {
|
|
||||||
fn from(error: PositionError) -> Self {
|
|
||||||
ReadingFileError::ReadPositionError(error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for ReadingFileError {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
match self {
|
|
||||||
ReadingFileError::ReadParseFenError(error) => error.fmt(f),
|
|
||||||
ReadingFileError::ReadFileError(error) => error.fmt(f),
|
|
||||||
ReadingFileError::ReadPositionError(error) => error.fmt(f),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn retrieve_chess_from_file_or_create(filename: &str) -> Result<Chess, ReadingFileError> {
|
|
||||||
match retrieve_chess_from_file(filename) {
|
|
||||||
Ok(chess) => Ok(chess),
|
|
||||||
Err(ReadingFileError::ReadFileError(error)) => {
|
|
||||||
if error.kind() == ErrorKind::NotFound {
|
|
||||||
create_default_fen_in_file(filename)
|
|
||||||
} else {
|
|
||||||
Err(ReadingFileError::ReadFileError(error))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
other_error => other_error,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn save_chess_position(chess: &Chess, filename: &str) -> std::io::Result<()> {
|
|
||||||
let mut file = File::create(filename)?;
|
|
||||||
file.write_all(fen::fen(chess).as_bytes())?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn retrieve_chess_from_file(filename: &str) -> Result<Chess, ReadingFileError> {
|
|
||||||
let mut file = File::open(filename)?;
|
|
||||||
let mut contents = String::new();
|
|
||||||
file.read_to_string(&mut contents)?;
|
|
||||||
let setup: Fen = contents.trim().parse()?;
|
|
||||||
let position: Chess = setup.position()?;
|
|
||||||
Ok(position)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn create_default_fen_in_file(filename: &str) -> Result<Chess, ReadingFileError> {
|
|
||||||
let chess = Chess::default();
|
|
||||||
save_chess_position(&Chess::default(), filename)?;
|
|
||||||
Ok(chess)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn board_representation(chess: &Chess, side: Color) -> String {
|
|
||||||
let mut s = String::from("");
|
|
||||||
let mut rank_numbers;
|
|
||||||
if side == Color::White {
|
|
||||||
rank_numbers = 8;
|
|
||||||
} else {
|
|
||||||
rank_numbers = 1;
|
|
||||||
}
|
|
||||||
for v in board_string_representation(chess, side) {
|
|
||||||
for square_to_print in v {
|
|
||||||
s.push_str(&format!(
|
|
||||||
"{}",
|
|
||||||
square_to_print
|
|
||||||
.square_representation
|
|
||||||
.color(square_to_print.color)
|
|
||||||
.on_color(square_to_print.background_color)
|
|
||||||
));
|
|
||||||
}
|
|
||||||
s.push_str(&format!("{}\n\r", rank_numbers));
|
|
||||||
if side == Color::White {
|
|
||||||
rank_numbers -= 1;
|
|
||||||
} else {
|
|
||||||
rank_numbers += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let mut files = vec!["a", "b", "c", "d", "e", "f", "g", "h"];
|
|
||||||
if side == Color::Black {
|
|
||||||
files.reverse();
|
|
||||||
}
|
|
||||||
for file in files {
|
|
||||||
s.push_str(&format!("{} ", file));
|
|
||||||
}
|
|
||||||
s
|
|
||||||
}
|
|
||||||
|
|
||||||
fn board_string_representation(chess: &Chess, side: Color) -> Vec<Vec<SquareToPrint>> {
|
|
||||||
let mut full_board_to_print = Vec::new();
|
|
||||||
for _ in 0..8 {
|
|
||||||
full_board_to_print.push(Vec::new())
|
|
||||||
}
|
|
||||||
for i in 0..8 {
|
|
||||||
for j in 0..8 {
|
|
||||||
let square = Square::new(i + 8 * j);
|
|
||||||
let square_to_print = SquareToPrint {
|
|
||||||
color: "black".to_string(),
|
|
||||||
background_color: if square.is_light() {
|
|
||||||
"white".to_string()
|
|
||||||
} else {
|
|
||||||
"green".to_string()
|
|
||||||
},
|
|
||||||
square_representation: get_square_representation(&square, chess),
|
|
||||||
};
|
|
||||||
full_board_to_print[j as usize].push(square_to_print);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if side == Color::White {
|
|
||||||
full_board_to_print.reverse();
|
|
||||||
} else {
|
|
||||||
for j in 0..8 {
|
|
||||||
full_board_to_print[j as usize].reverse();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
full_board_to_print
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn try_to_play_move(chess: &Chess, movestr: String) -> Result<Chess, MoveInputError> {
|
|
||||||
let san: San = movestr.parse()?;
|
|
||||||
let mv = san.to_move(chess)?;
|
|
||||||
Ok((*chess).clone().play(&mv)?)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_square_representation(square: &Square, chess: &Chess) -> String {
|
|
||||||
let board = (*chess).board();
|
|
||||||
match board.piece_at(*square) {
|
|
||||||
Some(piece) => format!("{} ", piece_char_to_utf8(piece.char())),
|
|
||||||
None => " ".to_string(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn piece_char_to_utf8(piece: char) -> char {
|
|
||||||
match piece {
|
|
||||||
'P' => '♙',
|
|
||||||
'p' => '♟',
|
|
||||||
'N' => '♘',
|
|
||||||
'n' => '♞',
|
|
||||||
'B' => '♗',
|
|
||||||
'b' => '♝',
|
|
||||||
'R' => '♖',
|
|
||||||
'r' => '♜',
|
|
||||||
'Q' => '♕',
|
|
||||||
'q' => '♛',
|
|
||||||
'K' => '♔',
|
|
||||||
'k' => '♚',
|
|
||||||
c => c,
|
|
||||||
}
|
|
||||||
}
|
|
255
src/lib.rs
255
src/lib.rs
@ -1,17 +1,246 @@
|
|||||||
use std::io;
|
use colored::Colorize;
|
||||||
pub mod chessboard;
|
use shakmaty::fen;
|
||||||
use shakmaty::{Chess, Color};
|
use shakmaty::fen::Fen;
|
||||||
|
use shakmaty::fen::ParseFenError;
|
||||||
|
use shakmaty::san::ParseSanError;
|
||||||
|
use shakmaty::san::San;
|
||||||
|
use shakmaty::san::SanError;
|
||||||
|
use shakmaty::{Chess, Color, IllegalMoveError, Position, PositionError, Setup, Square};
|
||||||
|
use std::fmt;
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io::prelude::*;
|
||||||
|
use std::io::{self, BufReader, ErrorKind, Read, Write};
|
||||||
|
use std::os::unix::net::UnixStream;
|
||||||
|
use std::str;
|
||||||
|
|
||||||
pub fn play() {
|
struct SquareToPrint {
|
||||||
let mut chess = Chess::default();
|
color: String,
|
||||||
loop {
|
background_color: String,
|
||||||
println!("{}", chessboard::board_representation(&chess, Color::White));
|
square_representation: String,
|
||||||
let mut input = String::new();
|
}
|
||||||
io::stdin().read_line(&mut input).unwrap();
|
|
||||||
print!("try to play: {}", input);
|
#[derive(Debug)]
|
||||||
match chessboard::try_to_play_move(&chess, String::from(input.trim())) {
|
pub enum MoveInputError {
|
||||||
Ok(played_chess) => chess = played_chess,
|
SanSanError(SanError),
|
||||||
Err(e) => println!("Error: {}", e),
|
SanParseSanError(ParseSanError),
|
||||||
|
ShakmatyIllegalMoveError(IllegalMoveError),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<SanError> for MoveInputError {
|
||||||
|
fn from(error: SanError) -> Self {
|
||||||
|
MoveInputError::SanSanError(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ParseSanError> for MoveInputError {
|
||||||
|
fn from(error: ParseSanError) -> Self {
|
||||||
|
MoveInputError::SanParseSanError(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<IllegalMoveError> for MoveInputError {
|
||||||
|
fn from(error: IllegalMoveError) -> Self {
|
||||||
|
MoveInputError::ShakmatyIllegalMoveError(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for MoveInputError {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
MoveInputError::SanSanError(san_error) => san_error.fmt(f),
|
||||||
|
MoveInputError::SanParseSanError(parse_san_error) => parse_san_error.fmt(f),
|
||||||
|
MoveInputError::ShakmatyIllegalMoveError(illegal_move_error) => {
|
||||||
|
illegal_move_error.fmt(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum ReadingFileError {
|
||||||
|
ReadParseFenError(ParseFenError),
|
||||||
|
ReadFileError(io::Error),
|
||||||
|
ReadPositionError(PositionError),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ParseFenError> for ReadingFileError {
|
||||||
|
fn from(error: ParseFenError) -> Self {
|
||||||
|
ReadingFileError::ReadParseFenError(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<io::Error> for ReadingFileError {
|
||||||
|
fn from(error: io::Error) -> Self {
|
||||||
|
ReadingFileError::ReadFileError(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<PositionError> for ReadingFileError {
|
||||||
|
fn from(error: PositionError) -> Self {
|
||||||
|
ReadingFileError::ReadPositionError(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for ReadingFileError {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
ReadingFileError::ReadParseFenError(error) => error.fmt(f),
|
||||||
|
ReadingFileError::ReadFileError(error) => error.fmt(f),
|
||||||
|
ReadingFileError::ReadPositionError(error) => error.fmt(f),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn retrieve_chess_from_file_or_create(filename: &str) -> Result<Chess, ReadingFileError> {
|
||||||
|
match retrieve_chess_from_file(filename) {
|
||||||
|
Ok(chess) => Ok(chess),
|
||||||
|
Err(ReadingFileError::ReadFileError(error)) => {
|
||||||
|
if error.kind() == ErrorKind::NotFound {
|
||||||
|
create_default_fen_in_file(filename)
|
||||||
|
} else {
|
||||||
|
Err(ReadingFileError::ReadFileError(error))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
other_error => other_error,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn save_chess_position(chess: &Chess, filename: &str) -> std::io::Result<()> {
|
||||||
|
let mut file = File::create(filename)?;
|
||||||
|
file.write_all(fen::fen(chess).as_bytes())?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn retrieve_chess_from_file(filename: &str) -> Result<Chess, ReadingFileError> {
|
||||||
|
let mut file = File::open(filename)?;
|
||||||
|
let mut contents = String::new();
|
||||||
|
file.read_to_string(&mut contents)?;
|
||||||
|
let setup: Fen = contents.trim().parse()?;
|
||||||
|
let position: Chess = setup.position()?;
|
||||||
|
Ok(position)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_default_fen_in_file(filename: &str) -> Result<Chess, ReadingFileError> {
|
||||||
|
let chess = Chess::default();
|
||||||
|
save_chess_position(&Chess::default(), filename)?;
|
||||||
|
Ok(chess)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn board_representation(chess: &Chess, side: Color) -> String {
|
||||||
|
let mut s = String::from("");
|
||||||
|
let mut rank_numbers;
|
||||||
|
if side == Color::White {
|
||||||
|
rank_numbers = 8;
|
||||||
|
} else {
|
||||||
|
rank_numbers = 1;
|
||||||
|
}
|
||||||
|
for v in board_string_representation(chess, side) {
|
||||||
|
for square_to_print in v {
|
||||||
|
s.push_str(&format!(
|
||||||
|
"{}",
|
||||||
|
square_to_print
|
||||||
|
.square_representation
|
||||||
|
.color(square_to_print.color)
|
||||||
|
.on_color(square_to_print.background_color)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
s.push_str(&format!("{}\n\r", rank_numbers));
|
||||||
|
if side == Color::White {
|
||||||
|
rank_numbers -= 1;
|
||||||
|
} else {
|
||||||
|
rank_numbers += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let mut files = vec!["a", "b", "c", "d", "e", "f", "g", "h"];
|
||||||
|
if side == Color::Black {
|
||||||
|
files.reverse();
|
||||||
|
}
|
||||||
|
for file in files {
|
||||||
|
s.push_str(&format!("{} ", file));
|
||||||
|
}
|
||||||
|
s.push_str("\n\r");
|
||||||
|
s
|
||||||
|
}
|
||||||
|
|
||||||
|
fn board_string_representation(chess: &Chess, side: Color) -> Vec<Vec<SquareToPrint>> {
|
||||||
|
let mut full_board_to_print = Vec::new();
|
||||||
|
for _ in 0..8 {
|
||||||
|
full_board_to_print.push(Vec::new())
|
||||||
|
}
|
||||||
|
for i in 0..8 {
|
||||||
|
for j in 0..8 {
|
||||||
|
let square = Square::new(i + 8 * j);
|
||||||
|
let square_to_print = SquareToPrint {
|
||||||
|
color: "black".to_string(),
|
||||||
|
background_color: if square.is_light() {
|
||||||
|
"white".to_string()
|
||||||
|
} else {
|
||||||
|
"green".to_string()
|
||||||
|
},
|
||||||
|
square_representation: get_square_representation(&square, chess),
|
||||||
};
|
};
|
||||||
|
full_board_to_print[j as usize].push(square_to_print);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if side == Color::White {
|
||||||
|
full_board_to_print.reverse();
|
||||||
|
} else {
|
||||||
|
for j in 0..8 {
|
||||||
|
full_board_to_print[j as usize].reverse();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
full_board_to_print
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn try_to_play_move(chess: &Chess, movestr: String) -> Result<Chess, MoveInputError> {
|
||||||
|
let san: San = movestr.parse()?;
|
||||||
|
let mv = san.to_move(chess)?;
|
||||||
|
Ok((*chess).clone().play(&mv)?)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_square_representation(square: &Square, chess: &Chess) -> String {
|
||||||
|
let board = (*chess).board();
|
||||||
|
match board.piece_at(*square) {
|
||||||
|
Some(piece) => format!("{} ", piece_char_to_utf8(piece.char())),
|
||||||
|
None => " ".to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn piece_char_to_utf8(piece: char) -> char {
|
||||||
|
match piece {
|
||||||
|
'P' => '♙',
|
||||||
|
'p' => '♟',
|
||||||
|
'N' => '♘',
|
||||||
|
'n' => '♞',
|
||||||
|
'B' => '♗',
|
||||||
|
'b' => '♝',
|
||||||
|
'R' => '♖',
|
||||||
|
'r' => '♜',
|
||||||
|
'Q' => '♕',
|
||||||
|
'q' => '♛',
|
||||||
|
'K' => '♔',
|
||||||
|
'k' => '♚',
|
||||||
|
c => c,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const DELIMITER_CHAR: u8 = 4;
|
||||||
|
|
||||||
|
pub fn read_from_stream(stream: &UnixStream) -> String {
|
||||||
|
let mut result = Vec::new();
|
||||||
|
let mut reader = BufReader::new(stream);
|
||||||
|
|
||||||
|
reader.read_until(DELIMITER_CHAR, &mut result).unwrap();
|
||||||
|
if let Some((_, msg)) = result.split_last() {
|
||||||
|
String::from(str::from_utf8(msg).unwrap())
|
||||||
|
} else {
|
||||||
|
String::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_to_stream(stream: &mut UnixStream, msg: String) {
|
||||||
|
let mut to_send = Vec::new();
|
||||||
|
to_send.append(&mut msg.into_bytes());
|
||||||
|
to_send.push(DELIMITER_CHAR);
|
||||||
|
stream.write_all(&to_send).unwrap();
|
||||||
|
}
|
||||||
|
@ -1,5 +0,0 @@
|
|||||||
use clichess;
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
clichess::play();
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user