use super::*;
use uncon::*;
use core::{cmp, mem, ops, ptr, u8};
use core::borrow::{Borrow, BorrowMut};
const VEC_CAP: usize = MoveVec::MAX_LEN;
#[repr(C)]
pub struct MoveVec {
buf: [u16; VEC_CAP],
len: u8,
}
impl<T: ?Sized + AsRef<[Move]>> PartialEq<T> for MoveVec {
#[inline]
fn eq(&self, other: &T) -> bool {
let this: &[u16] = &self.buf[..self.len as usize];
let that: &[u16] = unsafe { other.as_ref().into_unchecked() };
this == that
}
}
impl Eq for MoveVec {}
impl Clone for MoveVec {
#[inline]
fn clone(&self) -> MoveVec {
unsafe { ptr::read(self) }
}
#[inline]
fn clone_from(&mut self, source: &Self) {
unsafe { ptr::copy_nonoverlapping(source, self, 1) };
}
}
impl Default for MoveVec {
#[inline]
fn default() -> Self {
MoveVec { buf: unsafe { mem::uninitialized() }, len: 0 }
}
}
impl AsRef<[Move]> for MoveVec {
#[inline]
fn as_ref(&self) -> &[Move] { self }
}
impl AsMut<[Move]> for MoveVec {
#[inline]
fn as_mut(&mut self) -> &mut [Move] { self }
}
impl Borrow<[Move]> for MoveVec {
#[inline]
fn borrow(&self) -> &[Move] { self }
}
impl BorrowMut<[Move]> for MoveVec {
#[inline]
fn borrow_mut(&mut self) -> &mut [Move] { self }
}
impl ops::Deref for MoveVec {
type Target = [Move];
#[inline]
fn deref(&self) -> &[Move] {
let slice = &self.buf[..(self.len as usize)];
unsafe { slice.into_unchecked() }
}
}
impl ops::DerefMut for MoveVec {
#[inline]
fn deref_mut(&mut self) -> &mut [Move] {
let slice = &mut self.buf[..(self.len as usize)];
unsafe { slice.into_unchecked() }
}
}
impl MoveVec {
pub const MAX_LEN: usize = u8::MAX as usize;
#[inline]
pub fn new() -> MoveVec {
MoveVec::default()
}
#[inline]
pub fn from_elem(mv: Move, len: usize) -> MoveVec {
MoveVec::from_init(len, |_| mv)
}
#[inline]
pub fn from_init<F: FnMut(usize) -> Move>(len: usize, mut init: F) -> MoveVec {
let mut vec = MoveVec::new();
vec.len = cmp::min(len, VEC_CAP) as u8;
for (i, m) in vec.iter_mut().enumerate() {
unsafe { ptr::write(m, init(i)) };
}
vec
}
#[inline]
pub fn len(&self) -> usize {
self.len as usize
}
#[inline]
pub fn is_empty(&self) -> bool { self.len == 0 }
#[inline]
pub fn capacity(&self) -> usize { VEC_CAP }
#[inline]
pub fn clear(&mut self) { self.len = 0 }
#[inline]
pub fn push(&mut self, mv: Move) -> Option<Move> {
if self.len == u8::MAX {
Some(mv)
} else {
unsafe { ptr::write(&mut self.buf[self.len as usize], mv.0) };
self.len += 1;
None
}
}
#[inline]
pub fn push_swap(&mut self, mv: Move) -> Option<Move> {
self.push(mv).map(|mv| {
Move(mem::replace(&mut self.buf[VEC_CAP - 1], mv.0))
})
}
#[inline]
pub unsafe fn push_unchecked(&mut self, mv: Move) {
ptr::write(self.buf.get_unchecked_mut(self.len as usize), mv.0);
self.len = self.len.wrapping_add(1);
}
#[inline]
pub fn pop(&mut self) -> Option<Move> {
if self.len == 0 { None } else {
self.len -= 1;
Some(Move(self.buf[self.len as usize]))
}
}
#[inline]
pub fn remove_last(&mut self, n: usize) {
if n < self.len as usize {
self.len -= n as u8;
} else {
self.len = 0;
}
}
#[inline]
pub fn truncate(&mut self, len: usize) {
if len < (self.len as usize) {
self.len = len as u8;
}
}
#[inline]
pub unsafe fn set_len(&mut self, len: usize) {
self.len = cmp::min(len, VEC_CAP) as u8;
}
#[inline]
pub fn as_slice(&self) -> &[Move] { self }
#[inline]
pub fn as_mut_slice(&mut self) -> &mut [Move] { self }
}