use super::*;
pub struct OccupiedEntry<'a> {
map: &'a mut PieceMap,
key: Square,
}
impl<'a> fmt::Debug for OccupiedEntry<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("OccupiedEntry")
.field("key", self.key())
.field("value", self.get())
.finish()
}
}
impl<'a> OccupiedEntry<'a> {
#[inline]
pub fn key(&self) -> &Square { &self.key }
#[inline]
pub fn remove_entry(self) -> (Square, Piece) {
let key = self.key;
let buf = unsafe { self.map.as_bytes_mut() };
let val = mem::replace(&mut buf[key as usize], NONE);
unsafe { (key, val.into_unchecked()) }
}
#[inline]
pub fn get(&self) -> &Piece {
unsafe { self.map.get_unchecked(self.key) }
}
#[inline]
pub fn get_mut(&mut self) -> &mut Piece {
unsafe { self.map.get_unchecked_mut(self.key) }
}
#[inline]
pub fn into_mut(self) -> &'a mut Piece {
unsafe { self.map.get_unchecked_mut(self.key) }
}
#[inline]
pub fn insert(&mut self, piece: Piece) -> Piece {
let buf = unsafe { self.map.as_bytes_mut() };
let pc = mem::replace(&mut buf[self.key as usize], piece as u8);
unsafe { pc.into_unchecked() }
}
#[inline]
pub fn remove(self) -> Piece {
self.remove_entry().1
}
}
pub struct VacantEntry<'a> {
map: &'a mut PieceMap,
key: Square,
}
impl<'a> fmt::Debug for VacantEntry<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_tuple("VacantEntry")
.field(self.key())
.finish()
}
}
impl<'a> VacantEntry<'a> {
#[inline]
pub fn key(&self) -> &Square { &self.key }
#[inline]
pub fn into_key(self) -> Square { self.key }
#[inline]
pub fn insert(self, piece: Piece) -> &'a mut Piece {
unsafe {
let slot = &mut self.map.0.array[self.key as usize];
*slot = piece as u8;
slot.into_unchecked()
}
}
}
pub enum Entry<'a> {
Occupied(OccupiedEntry<'a>),
Vacant(VacantEntry<'a>),
}
impl<'a> fmt::Debug for Entry<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let field: &fmt::Debug = match *self {
Entry::Vacant(ref v) => v,
Entry::Occupied(ref o) => o,
};
f.debug_tuple("Entry").field(field).finish()
}
}
impl<'a> Entry<'a> {
#[inline]
pub(super) fn from_map(map: &'a mut PieceMap, sq: Square) -> Entry<'a> {
if map.contains(sq) {
Entry::Occupied(OccupiedEntry { map: map, key: sq })
} else {
Entry::Vacant(VacantEntry { map: map, key: sq })
}
}
#[inline]
pub fn or_insert(self, default: Piece) -> &'a mut Piece {
match self {
Entry::Occupied(entry) => entry.into_mut(),
Entry::Vacant(entry) => entry.insert(default),
}
}
#[inline]
pub fn or_insert_with<F>(self, default: F) -> &'a mut Piece
where F: FnOnce() -> Piece
{
match self {
Entry::Occupied(entry) => entry.into_mut(),
Entry::Vacant(entry) => entry.insert(default()),
}
}
#[inline]
pub fn key(&self) -> &Square {
match *self {
Entry::Occupied(ref entry) => entry.key(),
Entry::Vacant(ref entry) => entry.key(),
}
}
}