#![cfg_attr(not(feature = "std"), no_std)]
#[cfg(feature = "std")]
extern crate core;
use core::borrow::{Borrow, BorrowMut};
use core::cmp::Ordering;
use core::iter::FromIterator;
use core::ops;
#[allow(unused_imports)]
#[macro_use]
extern crate bit_collection_derive;
#[doc(hidden)]
pub use bit_collection_derive::*;
pub trait BitCollection: From<<Self as IntoIterator>::Item>
+ From<BitIter<Self>>
+ IntoIterator<IntoIter=BitIter<Self>>
+ FromIterator<<Self as IntoIterator>::Item>
+ Extend<<Self as IntoIterator>::Item>
+ ops::Not<Output=Self>
+ ops::BitAnd<Output=Self>
+ ops::BitAndAssign
+ ops::BitOr<Output=Self>
+ ops::BitOrAssign
+ ops::BitXor<Output=Self>
+ ops::BitXorAssign
+ ops::Sub<Output=Self>
+ ops::SubAssign
{
const FULL: Self;
const EMPTY: Self;
fn len(&self) -> usize;
fn is_empty(&self) -> bool;
fn has_multiple(&self) -> bool;
#[inline]
fn quantity(&self) -> Quantity {
use self::Quantity::*;
if self.is_empty() {
None
} else if self.has_multiple() {
Multiple
} else {
Single
}
}
#[inline]
fn as_iter(&mut self) -> &mut BitIter<Self> {
unsafe { &mut *(self as *mut _ as *mut _) }
}
#[inline]
fn into_bit(mut self) -> Option<Self::Item> {
let bit = self.pop_lsb();
if self.is_empty() { bit } else { None }
}
#[inline]
fn lsb(&self) -> Option<Self::Item> {
if self.is_empty() { None } else {
unsafe { Some(self.lsb_unchecked()) }
}
}
#[inline]
fn msb(&self) -> Option<Self::Item> {
if self.is_empty() { None } else {
unsafe { Some(self.msb_unchecked()) }
}
}
unsafe fn lsb_unchecked(&self) -> Self::Item;
unsafe fn msb_unchecked(&self) -> Self::Item;
fn remove_lsb(&mut self);
fn remove_msb(&mut self);
fn pop_lsb(&mut self) -> Option<Self::Item>;
fn pop_msb(&mut self) -> Option<Self::Item>;
fn contains<T: Into<Self>>(&self, T) -> bool;
#[inline]
fn removing<T: Into<Self>>(self, other: T) -> Self {
self - other.into()
}
#[inline]
fn inserting<T: Into<Self>>(self, other: T) -> Self {
self | other.into()
}
#[inline]
fn toggling<T: Into<Self>>(self, other: T) -> Self {
self ^ other.into()
}
#[inline]
fn intersecting<T: Into<Self>>(self, other: T) -> Self {
self & other.into()
}
#[inline]
fn setting<T: Into<Self>>(self, other: T, condition: bool) -> Self {
if condition {
self.inserting(other)
} else {
self.removing(other)
}
}
#[inline]
fn remove<T: Into<Self>>(&mut self, other: T) -> &mut Self {
*self -= other.into();
self
}
#[inline]
fn insert<T: Into<Self>>(&mut self, other: T) -> &mut Self {
*self |= other.into();
self
}
#[inline]
fn toggle<T: Into<Self>>(&mut self, other: T) -> &mut Self {
*self ^= other.into();
self
}
#[inline]
fn intersect<T: Into<Self>>(&mut self, other: T) -> &mut Self {
*self &= other.into();
self
}
#[inline]
fn set<T: Into<Self>>(&mut self, other: T, condition: bool) -> &mut Self {
if condition {
self.insert(other)
} else {
self.remove(other)
}
}
}
#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)]
pub struct BitIter<C: BitCollection>(pub C);
impl<C: BitCollection> From<C> for BitIter<C> {
#[inline(always)]
fn from(bits: C) -> Self { BitIter(bits) }
}
impl<C: BitCollection> AsRef<C> for BitIter<C> {
#[inline(always)]
fn as_ref(&self) -> &C { &self.0 }
}
impl<C: BitCollection> AsMut<C> for BitIter<C> {
#[inline(always)]
fn as_mut(&mut self) -> &mut C { &mut self.0 }
}
impl<C: BitCollection> Borrow<C> for BitIter<C> {
#[inline(always)]
fn borrow(&self) -> &C { self.as_ref() }
}
impl<C: BitCollection> BorrowMut<C> for BitIter<C> {
#[inline(always)]
fn borrow_mut(&mut self) -> &mut C { self.as_mut() }
}
impl<C: BitCollection> Iterator for BitIter<C> {
type Item = C::Item;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.0.pop_lsb()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.len();
(len, Some(len))
}
#[inline]
fn count(self) -> usize {
self.len()
}
#[inline]
fn last(self) -> Option<Self::Item> {
self.0.msb()
}
}
impl<C: BitCollection> DoubleEndedIterator for BitIter<C> {
#[inline]
fn next_back(&mut self) -> Option<Self::Item> {
self.0.pop_msb()
}
}
impl<C: BitCollection> ExactSizeIterator for BitIter<C> {
#[inline]
fn len(&self) -> usize {
self.0.len()
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
pub enum Quantity {
Multiple,
Single,
None,
}
impl PartialOrd for Quantity {
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
#[inline]
fn lt(&self, other: &Self) -> bool { (*self as usize) > (*other as usize) }
#[inline]
fn gt(&self, other: &Self) -> bool { (*self as usize) < (*other as usize) }
#[inline]
fn le(&self, other: &Self) -> bool { (*self as usize) >= (*other as usize) }
#[inline]
fn ge(&self, other: &Self) -> bool { (*self as usize) <= (*other as usize) }
}
impl Ord for Quantity {
#[inline]
fn cmp(&self, other: &Self) -> Ordering {
use Ordering::*;
match (*self as usize).cmp(&(*other as usize)) {
Equal => Equal,
Greater => Less,
Less => Greater,
}
}
}