use crate::protocol::{Color, DecodePositionNotificationError, Piece, PieceKind, Square};
pub(crate) fn encode_piece(piece: Option<Piece>) -> u8 {
use Color::{Black, White};
use PieceKind::{Bishop, King, Knight, Pawn, Queen, Rook};
match piece {
None => 0x0,
Some(Piece {
color: Black,
kind: Queen,
}) => 0x1,
Some(Piece {
color: Black,
kind: King,
}) => 0x2,
Some(Piece {
color: Black,
kind: Bishop,
}) => 0x3,
Some(Piece {
color: Black,
kind: Pawn,
}) => 0x4,
Some(Piece {
color: Black,
kind: Knight,
}) => 0x5,
Some(Piece {
color: White,
kind: Rook,
}) => 0x6,
Some(Piece {
color: White,
kind: Pawn,
}) => 0x7,
Some(Piece {
color: Black,
kind: Rook,
}) => 0x8,
Some(Piece {
color: White,
kind: Bishop,
}) => 0x9,
Some(Piece {
color: White,
kind: Knight,
}) => 0xa,
Some(Piece {
color: White,
kind: Queen,
}) => 0xb,
Some(Piece {
color: White,
kind: King,
}) => 0xc,
}
}
pub(crate) fn decode_piece(
square: Square,
value: u8,
) -> Result<Option<Piece>, DecodePositionNotificationError> {
use Color::{Black, White};
use PieceKind::{Bishop, King, Knight, Pawn, Queen, Rook};
match value {
0x0 => Ok(None),
0x1 => Ok(Some(Piece {
color: Black,
kind: Queen,
})),
0x2 => Ok(Some(Piece {
color: Black,
kind: King,
})),
0x3 => Ok(Some(Piece {
color: Black,
kind: Bishop,
})),
0x4 => Ok(Some(Piece {
color: Black,
kind: Pawn,
})),
0x5 => Ok(Some(Piece {
color: Black,
kind: Knight,
})),
0x6 => Ok(Some(Piece {
color: White,
kind: Rook,
})),
0x7 => Ok(Some(Piece {
color: White,
kind: Pawn,
})),
0x8 => Ok(Some(Piece {
color: Black,
kind: Rook,
})),
0x9 => Ok(Some(Piece {
color: White,
kind: Bishop,
})),
0xa => Ok(Some(Piece {
color: White,
kind: Knight,
})),
0xb => Ok(Some(Piece {
color: White,
kind: Queen,
})),
0xc => Ok(Some(Piece {
color: White,
kind: King,
})),
value => Err(DecodePositionNotificationError::InvalidPiece { square, value }),
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::protocol::square::{File, Rank};
const PIECE_CODES: [(u8, Option<Piece>); 13] = [
(0x0, None),
(
0x1,
Some(Piece {
color: Color::Black,
kind: PieceKind::Queen,
}),
),
(
0x2,
Some(Piece {
color: Color::Black,
kind: PieceKind::King,
}),
),
(
0x3,
Some(Piece {
color: Color::Black,
kind: PieceKind::Bishop,
}),
),
(
0x4,
Some(Piece {
color: Color::Black,
kind: PieceKind::Pawn,
}),
),
(
0x5,
Some(Piece {
color: Color::Black,
kind: PieceKind::Knight,
}),
),
(
0x6,
Some(Piece {
color: Color::White,
kind: PieceKind::Rook,
}),
),
(
0x7,
Some(Piece {
color: Color::White,
kind: PieceKind::Pawn,
}),
),
(
0x8,
Some(Piece {
color: Color::Black,
kind: PieceKind::Rook,
}),
),
(
0x9,
Some(Piece {
color: Color::White,
kind: PieceKind::Bishop,
}),
),
(
0xa,
Some(Piece {
color: Color::White,
kind: PieceKind::Knight,
}),
),
(
0xb,
Some(Piece {
color: Color::White,
kind: PieceKind::Queen,
}),
),
(
0xc,
Some(Piece {
color: Color::White,
kind: PieceKind::King,
}),
),
];
#[test]
fn encodes_and_decodes_every_piece_code() {
let square = Square::new(File::E, Rank::Four);
for (code, piece) in PIECE_CODES {
assert_eq!(encode_piece(piece), code);
assert_eq!(decode_piece(square, code), Ok(piece));
}
}
#[test]
fn rejects_unknown_piece_codes_with_the_square() {
let square = Square::new(File::B, Rank::Seven);
for value in 0xd..=u8::MAX {
assert_eq!(
decode_piece(square, value),
Err(DecodePositionNotificationError::InvalidPiece { square, value })
);
}
}
}