#![feature(alloc)]
#![cfg_attr(feature="nightly", feature(plugin))]
#![cfg_attr(feature="nightly", plugin(clippy))]
extern crate alloc;
extern crate num;
extern crate typenum;
use alloc::raw_vec::RawVec;
use num::PrimInt;
use std::cmp;
use std::fmt::{self, Debug};
use std::hash::{self, Hash};
use std::mem;
use std::ptr;
use std::slice;
use std::ops::{BitAnd, BitOr, Shl, Shr};
use std::marker::{PhantomData, Send, Sync};
use typenum::NonZero;
use typenum::uint::Unsigned;
pub struct NbitsVec<N: Unsigned + NonZero, Block: PrimInt = usize> {
buf: RawVec<Block>,
len: usize,
_marker: PhantomData<N>,
}
impl<N: Unsigned + NonZero, Block: PrimInt> NbitsVec<N, Block> {
#[inline]
pub fn new() -> Self {
Self::check_if_n_valid();
NbitsVec {
buf: RawVec::new(),
len: 0,
_marker: PhantomData,
}
}
#[inline]
pub fn with_capacity(capacity: usize) -> Self {
Self::check_if_n_valid();
NbitsVec {
buf: RawVec::with_capacity(Self::raw_cap_from(capacity)),
len: 0,
_marker: PhantomData,
}
}
#[inline]
pub unsafe fn from_raw_parts(ptr: *mut Block, length: usize, capacity: usize) -> Self {
Self::check_if_n_valid();
NbitsVec {
buf: RawVec::from_raw_parts(ptr, Self::raw_cap_from(capacity)),
len: length,
_marker: PhantomData,
}
}
#[inline]
pub fn capacity(&self) -> usize {
Self::cap_from(self.buf.cap())
}
#[inline]
pub fn reserve(&mut self, additional: usize) {
let required_cap = self.len().checked_add(additional).expect("capacity overflow");
let used_cap = Self::raw_cap_from(self.len());
let need_extra_cap = Self::raw_cap_from(required_cap);
self.buf.reserve(used_cap, need_extra_cap);
}
#[inline]
pub fn reserve_exact(&mut self, additional: usize) {
let required_cap = self.len().checked_add(additional).expect("capacity overflow");
let used_cap = Self::raw_cap_from(self.len());
let need_extra_cap = Self::raw_cap_from(required_cap);
self.buf.reserve_exact(used_cap, need_extra_cap);
}
#[inline]
pub fn shrink_to_fit(&mut self) {
let fit_len = Self::raw_cap_from(self.len());
self.buf.shrink_to_fit(fit_len);
}
#[inline]
pub fn truncate(&mut self, len: usize) {
if self.len() > len {
self.len = len;
self.shrink_to_fit();
}
}
#[inline]
pub unsafe fn set_len(&mut self, len: usize) {
self.len = len;
}
#[inline]
pub fn insert(&mut self, index: usize, element: Block) {
self.align(index, index + 1);
self.set(index, element);
}
#[inline]
pub fn remove(&mut self, index: usize) -> Block {
if index >= self.len {
panic!("index is out of bounds");
}
if self.is_empty() {
panic!("vector is empty");
}
if self.len() == 1 {
return self.pop().expect("swap removed with one element");
}
let removed = self.get(index);
self.align(index + 1, index);
removed
}
#[inline]
pub fn swap_remove(&mut self, index: usize) -> Block {
if index >= self.len {
panic!("index is out of bounds");
}
if self.is_empty() {
panic!("vector is empty");
}
if self.len() == 1 {
return self.pop().expect("swap removed with one element");
}
let value = self.get(index);
let last = self.pop().expect("swap removed with last element");
self.set(index, last);
value
}
#[inline]
pub fn append(&mut self, other: &mut Self) {
let other_len = other.len();
self.reserve_exact(other_len);
for i in 0..other_len {
let v = other.get(i);
self.push(v);
}
unsafe { other.set_len(0) }
}
#[inline]
pub fn clear(&mut self) {
self.len = 0;
}
#[inline]
pub fn len(&self) -> usize {
self.len
}
#[inline]
pub fn bits(&self) -> usize {
self.len() * Self::nbits()
}
#[inline]
pub fn cap_bits(&self) -> usize {
self.raw_cap() * Self::block_bits()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
#[inline]
pub fn push(&mut self, value: Block) {
let len = self.len();
if self.capacity() == len {
self.reserve(1);
}
self.len += 1;
self.set(len, value);
}
#[inline]
pub fn pop(&mut self) -> Option<Block> {
if self.len == 0 {
None
} else {
let ret = Some(self.get(self.len() - 1));
self.len -= 1;
ret
}
}
#[inline]
pub fn resize(&mut self, new_len: usize, value: Block) {
let len = self.len();
if len < new_len {
let n = new_len - len;
self.reserve_exact(n);
self.len = new_len;
self.fill(len, n, value);
} else {
self.truncate(new_len);
}
}
#[inline]
pub fn align(&mut self, from: usize, to: usize) {
if from > to {
let interval = from - to;
for from in from..self.len() {
let value = self.get(from);
self.set(from - interval, value);
}
self.len = self.len - interval;
} else {
let interval = to - from;
let len = self.len();
self.reserve_exact(interval);
self.len = len + interval;
for from in (from..len).rev() {
let value = self.get(from);
self.set(from + interval, value);
}
self.fill(from, interval, Block::zero());
}
}
#[inline]
pub fn fill(&mut self, index: usize, length: usize, value: Block) {
for i in index..cmp::min(index + length, self.len) {
unsafe { self.unchecked_set(i, value) }
}
}
#[inline]
pub fn set(&mut self, index: usize, value: Block) {
if index >= self.len {
panic!("attempt to set at {} but only {}", index, self.len);
}
unsafe { self.unchecked_set(index, value) }
}
#[inline]
unsafe fn unchecked_set(&mut self, index: usize, value: Block) {
let nbits = Self::nbits();
let offset = index * nbits;
if nbits == 1 {
self.set_raw_bit(offset, value & Block::one() == Block::one());
return;
}
let bi = Self::bit_index(offset);
if Self::is_packed() {
let ptr = self.buf.ptr().offset(bi as isize);
ptr::write(ptr, value);
return;
}
let bo = Self::bit_offset(offset);
let bo2 = Self::bit_offset(offset + nbits);
let block_bits = Self::block_bits();
if Self::is_aligned() || bo < bo2 || bo2 == 0 {
let mask = Self::mask();
let ptr = self.buf.ptr().offset(bi as isize);
let ori = ptr::read(ptr);
let new = ori & !(mask << bo) | ((value & mask) << bo);
if ori != new {
ptr::write(ptr, new);
}
} else {
let mask = Self::mask();
let ptr = self.buf.ptr().offset(bi as isize);
let ori = ptr::read(ptr);
let new = Block::zero()
.not()
.shr(block_bits - bo)
.bitand(ori)
.bitor(value.bitand(mask).shl(bo));
if ori != new {
ptr::write(ptr, new);
}
let ptr = ptr.offset(1);
let ori = ptr::read(ptr);
let new = value.shr(nbits - bo2).bitand(mask).bitor(mask.not().bitand(ori));
if ori != new {
ptr::write(ptr, new);
}
}
}
#[inline]
pub unsafe fn set_raw_bits(&mut self, pos: usize, length: usize, value: Block) {
let block_bits = Self::block_bits();
let loc = Self::bit_loc(pos);
debug_assert!(length > 0 && length <= block_bits);
if loc.0 >= self.raw_cap() {
println!("index out of bounds");
return;
}
let ptr = self.raw_mut_ptr().offset(loc.0 as isize);
let ori = ptr::read(ptr);
if length == 1 {
let mask = Block::one() << loc.1;
let old = (ori >> loc.1) & Block::one();
let new = value & Block::one();
if old != new {
if new == Block::one() {
ptr::write(ptr, ori | mask)
} else {
ptr::write(ptr, !mask & ori)
}
}
return;
}
if length == block_bits && loc.1 == 0 {
ptr::write(ptr, value);
return;
}
let remain = block_bits - length;
let mask = !Block::zero() >> remain;
if loc.1 == 0 {
let new = value & mask | (ori & !mask);
if ori != new {
ptr::write(ptr, new);
}
return;
}
let end_off = (loc.1 + length) % block_bits;
if end_off == 0 {
let new = ((value & mask) << loc.1) | (ori & (!mask >> length));
if ori != new {
ptr::write(ptr, new);
}
return;
}
if end_off > loc.1 {
let new = ori & !(mask << loc.1) | ((value & mask) << loc.1);
if ori != new {
ptr::write(ptr, new);
}
return;
}
if self.raw_cap() == loc.0 + 1 {
let new = ((value & mask) << loc.1) | (ori & (!mask >> (block_bits - loc.1)));
if ori != new {
ptr::write(ptr, new);
}
return;
}
let new = Block::zero().not().shr(block_bits - loc.1).bitand(ori).bitor(value.shl(loc.1));
if ori != new {
ptr::write(ptr, new);
}
let ptr = ptr.offset(1);
let ori = ptr::read(ptr);
let remain = block_bits - end_off;
let mask = Block::zero().not().shr(remain);
let new = value.shr(length - end_off).bitand(mask).bitor(mask.not().bitand(ori));
if ori != new {
ptr::write(ptr, new);
}
}
#[inline]
pub unsafe fn set_raw_bit(&mut self, offset: usize, bit: bool) {
let loc = Self::bit_loc(offset);
let mask = Block::one() << loc.1;
let ptr = self.buf.ptr().offset(loc.0 as isize);
let cur = ptr::read(ptr);
let old = cur >> loc.1 & Block::one();
match (old == Block::one(), bit) {
(lhs, rhs) if lhs == rhs => (),
(_, true) => ptr::write(ptr, cur | mask),
(_, false) => ptr::write(ptr, cur & !mask),
}
}
#[inline]
pub fn get(&self, index: usize) -> Block {
if index >= self.len {
panic!("index out of bounds: attempt to get at {} but only {}",
index,
self.len);
}
let nbits = Self::nbits();
let bit_pos = index * nbits;
let bi = Self::bit_index(bit_pos);
let bo = Self::bit_offset(bit_pos);
unsafe {
let ptr = self.raw_ptr().offset(bi as isize);
if nbits == 1 {
return ptr::read(ptr) >> bo & Block::one();
}
let bo2 = Self::bit_offset(bit_pos + nbits);
let block_bits = Self::block_bits();
if bo2 == 0 {
ptr::read(ptr) >> (block_bits - nbits)
} else if bo < bo2 {
ptr::read(ptr) << (block_bits - bo2) >> (block_bits - nbits)
} else {
(ptr::read(ptr) >> bo) |
(ptr::read(ptr.offset(1)) << (block_bits - bo2) >> (block_bits - nbits))
}
}
}
#[inline]
pub unsafe fn get_raw_bits(&self, pos: usize, length: usize) -> Block {
debug_assert!(length > 0 && length <= Self::block_bits());
let loc = Self::bit_loc(pos);
if loc.0 >= self.raw_cap() {
return Block::zero();
}
let ptr = self.raw_ptr().offset(loc.0 as isize);
if length == 1 {
return ptr::read(ptr) >> loc.1 & Block::one();
}
let block_bits = Self::block_bits();
if length == block_bits && loc.1 == 0 {
return ptr::read(ptr);
}
let end_off = (loc.1 + length) % block_bits;
if end_off == 0 {
return ptr::read(ptr) >> (block_bits - length);
}
if end_off > loc.1 {
return ptr::read(ptr) << (block_bits - end_off) >> (block_bits - length);
}
if self.raw_cap() == loc.0 + 1 {
return ptr::read(ptr) >> loc.1;
}
if length == block_bits {
return ptr::read(ptr) >> loc.1 | (ptr::read(ptr.offset(1)) << (block_bits - loc.1));
}
let e = block_bits - end_off;
(ptr::read(ptr) >> loc.1) | (ptr::read(ptr.offset(1)) << e >> (block_bits - length))
}
#[inline]
pub unsafe fn get_raw_bit(&self, pos: usize) -> bool {
self.get_raw_bits(pos, 1) == Block::one()
}
#[inline]
pub fn raw_mut_ptr(&mut self) -> *mut Block {
self.buf.ptr()
}
#[inline]
pub fn raw_ptr(&self) -> *const Block {
self.buf.ptr()
}
#[inline]
pub fn as_raw_slice(&self) -> &[Block] {
unsafe {
let p = self.buf.ptr();
debug_assert!(!p.is_null());
slice::from_raw_parts(p, self.used_raw_cap())
}
}
#[inline]
pub fn as_mut_raw_slice(&mut self) -> &mut [Block] {
unsafe {
let p = self.buf.ptr();
debug_assert!(!p.is_null());
slice::from_raw_parts_mut(p, self.used_raw_cap())
}
}
#[inline]
pub fn into_raw_boxed_slice(mut self) -> Box<[Block]> {
unsafe {
self.shrink_to_fit();
let buf = ptr::read(&self.buf);
mem::forget(self);
buf.into_box()
}
}
#[inline]
fn used_raw_cap(&self) -> usize {
let loc = Self::bit_loc(self.bits());
if loc.1 == 0 {
loc.0
} else {
loc.0 + 1
}
}
#[inline]
fn raw_cap(&self) -> usize {
self.buf.cap()
}
#[inline]
fn is_aligned() -> bool {
Self::block_bits() % Self::nbits() == 0
}
#[inline]
fn is_packed() -> bool {
Self::block_bits() == Self::nbits()
}
#[inline]
fn raw_cap_from(cap: usize) -> usize {
let loc = Self::loc(cap);
if loc.1 == 0 {
loc.0
} else {
loc.0 + 1
}
}
#[inline]
fn cap_from(raw_cap: usize) -> usize {
raw_cap * Self::block_bits() / Self::nbits()
}
#[inline]
fn loc(index: usize) -> Loc {
let bits = index * Self::nbits();
let rbits = Self::block_bits();
(bits / rbits, bits % rbits)
}
#[inline]
fn bit_loc(bit: usize) -> BitLoc {
let rbits = Self::block_bits();
(bit / rbits, bit % rbits)
}
#[inline]
fn bit_offset(bit: usize) -> usize {
bit % Self::block_bits()
}
#[inline]
fn bit_index(bit: usize) -> usize {
bit / Self::block_bits()
}
#[inline]
fn block_bits() -> usize {
mem::size_of::<Block>() * 8
}
#[inline]
pub fn nbits() -> usize {
N::to_usize()
}
#[inline]
pub fn mask() -> Block {
Block::zero().not().shr(Self::block_bits() - Self::nbits())
}
#[inline]
fn check_if_n_valid() {
if Self::nbits() > Self::block_bits() {
panic!("`N` should be less than block's bits count, while your expect storing \
`{}`bits in a `{}`bits block vector",
Self::nbits(),
Self::block_bits());
}
}
}
type Loc = (usize, usize);
type BitLoc = Loc;
impl<N: Unsigned + NonZero, Block: PrimInt> Default for NbitsVec<N, Block> {
fn default() -> Self {
NbitsVec {
buf: RawVec::new(),
len: 0,
_marker: PhantomData,
}
}
}
impl<N: Unsigned + NonZero, Block: PrimInt + fmt::LowerHex> Debug for NbitsVec<N, Block> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
try!(write!(f,
"NbitsVec<{}> {{ len: {}, buf: RawVec {{ cap: {}, [",
N::to_usize(),
self.len,
self.buf.cap()));
let ptr = self.buf.ptr();
for i in 0..self.buf.cap() {
unsafe {
try!(write!(f, "{:#x}, ", ptr::read(ptr.offset(i as isize))));
}
}
write!(f, "] }}")
}
}
impl<N: Unsigned + NonZero, Block: PrimInt + Hash> Hash for NbitsVec<N, Block> {
#[inline]
fn hash<H: hash::Hasher>(&self, state: &mut H) {
Hash::hash(self.as_raw_slice(), state);
}
}
impl<N: Unsigned + NonZero, Block: PrimInt> PartialEq for NbitsVec<N, Block> {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.len() == other.len() && self.as_raw_slice() == other.as_raw_slice()
}
#[inline]
fn ne(&self, other: &Self) -> bool {
self.len() != other.len() || self.as_raw_slice() == other.as_raw_slice()
}
}
impl<N: Unsigned + NonZero, Block: PrimInt> Eq for NbitsVec<N, Block> {}
impl<N: Unsigned + NonZero, Block: PrimInt> Clone for NbitsVec<N, Block> {
fn clone(&self) -> Self {
let mut new = Self::with_capacity(self.len());
unsafe {
ptr::copy_nonoverlapping(self.buf.ptr(), new.buf.ptr(), self.used_raw_cap());
new.set_len(self.len());
}
new
}
}
impl<N: Unsigned + NonZero, Block: PrimInt> PartialOrd for NbitsVec<N, Block> {
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
PartialOrd::partial_cmp(self.as_raw_slice(), other.as_raw_slice())
}
}
impl<N: Unsigned + NonZero, Block: PrimInt> Ord for NbitsVec<N, Block> {
fn cmp(&self, other: &Self) -> cmp::Ordering {
Ord::cmp(self.as_raw_slice(), other.as_raw_slice())
}
}
unsafe impl<N: Unsigned + NonZero, Block: PrimInt> Send for NbitsVec<N, Block> {}
unsafe impl<N: Unsigned + NonZero, Block: PrimInt> Sync for NbitsVec<N, Block> {}
#[cfg_attr(rustfmt, rustfmt_skip)]
pub use typenum::consts::{
U1 as N1,
U2 as N2,
U3 as N3,
U4 as N4,
U5 as N5,
U6 as N6,
U7 as N7,
U8 as N8,
U9 as N9,
U10 as N10,
U11 as N11,
U12 as N12,
U13 as N13,
U14 as N14,
U15 as N15,
U16 as N16,
U17 as N17,
U18 as N18,
U19 as N19,
U20 as N20,
U21 as N21,
U22 as N22,
U23 as N23,
U24 as N24,
U25 as N25,
U26 as N26,
U27 as N27,
U28 as N28,
U29 as N29,
U30 as N30,
U31 as N31,
U32 as N32,
U33 as N33,
U34 as N34,
U35 as N35,
U36 as N36,
U37 as N37,
U38 as N38,
U39 as N39,
U40 as N40,
U41 as N41,
U42 as N42,
U43 as N43,
U44 as N44,
U45 as N45,
U46 as N46,
U47 as N47,
U48 as N48,
U49 as N49,
U50 as N50,
U51 as N51,
U52 as N52,
U53 as N53,
U54 as N54,
U55 as N55,
U56 as N56,
U57 as N57,
U58 as N58,
U59 as N59,
U60 as N60,
U61 as N61,
U62 as N62,
U63 as N63,
};
#[cfg(test)]
mod tests;