use std::borrow::Borrow;
use std::cmp::Ordering;
use std::collections;
use std::fmt::{Debug, Error, Formatter};
use std::hash::{Hash, Hasher};
use std::iter::{FromIterator, IntoIterator};
use std::ops::{Add, Mul};
use std::sync::Arc;
use hashset::HashSet;
use ordmap::{self, OrdMap};
use shared::Shared;
#[macro_export]
macro_rules! ordset {
() => { $crate::ordset::OrdSet::new() };
( $($x:expr),* ) => {{
let mut l = $crate::ordset::OrdSet::new();
$(
l = l.insert($x);
)*
l
}};
}
pub struct OrdSet<A>(OrdMap<A, ()>);
impl<A> OrdSet<A> {
pub fn new() -> Self {
OrdSet(OrdMap::new())
}
pub fn singleton<R>(a: R) -> Self
where
R: Shared<A>,
{
OrdSet(OrdMap::<A, ()>::singleton(a, ()))
}
pub fn iter(&self) -> Iter<A> {
Iter { it: self.0.iter() }
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
pub fn len(&self) -> usize {
self.0.len()
}
pub fn get_min(&self) -> Option<Arc<A>> {
self.0.get_min().map(|(a, _)| a)
}
pub fn get_max(&self) -> Option<Arc<A>> {
self.0.get_max().map(|(a, _)| a)
}
}
impl<A: Ord> OrdSet<A> {
pub fn insert<R>(&self, a: R) -> Self
where
R: Shared<A>,
{
OrdSet(self.0.insert(a, ()))
}
#[inline]
pub fn insert_mut<R>(&mut self, a: R)
where
R: Shared<A>,
{
self.0.insert_mut(a, ())
}
pub fn contains(&self, a: &A) -> bool {
self.0.contains_key(a)
}
pub fn remove(&self, a: &A) -> Self {
OrdSet(self.0.remove(a))
}
#[inline]
pub fn remove_mut<R>(&mut self, a: &A) {
self.0.remove_mut(a)
}
pub fn union<RS>(&self, other: RS) -> Self
where
RS: Borrow<Self>,
{
OrdSet(self.0.union(&other.borrow().0))
}
pub fn unions<I>(i: I) -> Self
where
I: IntoIterator<Item = Self>,
{
i.into_iter().fold(ordset![], |a, b| a.union(&b))
}
pub fn difference<RS>(&self, other: RS) -> Self
where
RS: Borrow<Self>,
{
OrdSet(self.0.difference(&other.borrow().0))
}
pub fn intersection<RS>(&self, other: RS) -> Self
where
RS: Borrow<Self>,
{
OrdSet(self.0.intersection(&other.borrow().0))
}
pub fn split(&self, split: &A) -> (Self, Self) {
let (l, r) = self.0.split(split);
(OrdSet(l), OrdSet(r))
}
pub fn split_member(&self, split: &A) -> (Self, bool, Self) {
let (l, m, r) = self.0.split_lookup(split);
(OrdSet(l), m.is_some(), OrdSet(r))
}
pub fn is_subset<RS>(&self, other: RS) -> bool
where
RS: Borrow<Self>,
{
self.0.is_submap(&other.borrow().0)
}
pub fn is_proper_subset<RS>(&self, other: RS) -> bool
where
RS: Borrow<Self>,
{
self.0.is_proper_submap(&other.borrow().0)
}
pub fn take(&self, n: usize) -> Self {
OrdSet(self.0.take(n))
}
pub fn drop(&self, n: usize) -> Self {
OrdSet(self.0.drop(n))
}
pub fn pop_min(&self) -> (Option<Arc<A>>, Self) {
let (pair, set) = self.0.pop_min_with_key();
(pair.map(|(a, _)| a), OrdSet(set))
}
pub fn pop_max(&self) -> (Option<Arc<A>>, Self) {
let (pair, set) = self.0.pop_max_with_key();
(pair.map(|(a, _)| a), OrdSet(set))
}
pub fn remove_min(&self) -> Self {
self.pop_min().1
}
pub fn remove_max(&self) -> Self {
self.pop_max().1
}
}
impl<A> Clone for OrdSet<A> {
fn clone(&self) -> Self {
OrdSet(self.0.clone())
}
}
impl<A: Ord + PartialEq> PartialEq for OrdSet<A> {
fn eq(&self, other: &Self) -> bool {
self.0 == other.0
}
}
impl<A: Ord + Eq> Eq for OrdSet<A> {}
impl<A: Ord> PartialOrd for OrdSet<A> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
self.0.partial_cmp(&other.0)
}
}
impl<A: Ord> Ord for OrdSet<A> {
fn cmp(&self, other: &Self) -> Ordering {
self.0.cmp(&other.0)
}
}
impl<A: Ord + Hash> Hash for OrdSet<A> {
fn hash<H>(&self, state: &mut H)
where
H: Hasher,
{
for i in self.iter() {
i.hash(state);
}
}
}
impl<A> Default for OrdSet<A> {
fn default() -> Self {
ordset![]
}
}
impl<'a, A: Ord> Add for &'a OrdSet<A> {
type Output = OrdSet<A>;
fn add(self, other: Self) -> Self::Output {
self.union(other)
}
}
impl<'a, A: Ord> Mul for &'a OrdSet<A> {
type Output = OrdSet<A>;
fn mul(self, other: Self) -> Self::Output {
self.intersection(other)
}
}
impl<A: Ord + Debug> Debug for OrdSet<A> {
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
write!(f, "{{ ")?;
let mut it = self.iter().peekable();
loop {
match it.next() {
None => break,
Some(a) => {
write!(f, "{:?}", a)?;
match it.peek() {
None => write!(f, " }}")?,
Some(_) => write!(f, ", ")?,
}
}
}
}
Ok(())
}
}
pub struct Iter<A> {
it: ordmap::Iter<A, ()>,
}
impl<A> Iterator for Iter<A>
where
A: Ord,
{
type Item = Arc<A>;
fn next(&mut self) -> Option<Self::Item> {
self.it.next().map(|(a, _)| a)
}
}
impl<A: Ord, RA> FromIterator<RA> for OrdSet<A>
where
RA: Shared<A>,
{
fn from_iter<T>(i: T) -> Self
where
T: IntoIterator<Item = RA>,
{
i.into_iter().fold(ordset![], |s, a| s.insert(a))
}
}
impl<'a, A> IntoIterator for &'a OrdSet<A>
where
A: Ord,
{
type Item = Arc<A>;
type IntoIter = Iter<A>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<A> IntoIterator for OrdSet<A>
where
A: Ord,
{
type Item = Arc<A>;
type IntoIter = Iter<A>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<'a, A: Ord + Clone> From<&'a [A]> for OrdSet<A> {
fn from(slice: &'a [A]) -> Self {
slice.into_iter().cloned().collect()
}
}
impl<'a, A: Ord> From<&'a [Arc<A>]> for OrdSet<A> {
fn from(slice: &'a [Arc<A>]) -> Self {
slice.into_iter().cloned().collect()
}
}
impl<A: Ord> From<Vec<A>> for OrdSet<A> {
fn from(vec: Vec<A>) -> Self {
vec.into_iter().collect()
}
}
impl<'a, A: Ord + Clone> From<&'a Vec<A>> for OrdSet<A> {
fn from(vec: &Vec<A>) -> Self {
vec.into_iter().cloned().collect()
}
}
impl<'a, A: Ord> From<&'a Vec<Arc<A>>> for OrdSet<A> {
fn from(vec: &Vec<Arc<A>>) -> Self {
vec.into_iter().cloned().collect()
}
}
impl<A: Eq + Hash + Ord> From<collections::HashSet<A>> for OrdSet<A> {
fn from(hash_set: collections::HashSet<A>) -> Self {
hash_set.into_iter().collect()
}
}
impl<'a, A: Eq + Hash + Ord + Clone> From<&'a collections::HashSet<A>> for OrdSet<A> {
fn from(hash_set: &collections::HashSet<A>) -> Self {
hash_set.into_iter().cloned().collect()
}
}
impl<'a, A: Eq + Hash + Ord> From<&'a collections::HashSet<Arc<A>>> for OrdSet<A> {
fn from(hash_set: &collections::HashSet<Arc<A>>) -> Self {
hash_set.into_iter().cloned().collect()
}
}
impl<A: Ord> From<collections::BTreeSet<A>> for OrdSet<A> {
fn from(btree_set: collections::BTreeSet<A>) -> Self {
btree_set.into_iter().collect()
}
}
impl<'a, A: Ord + Clone> From<&'a collections::BTreeSet<A>> for OrdSet<A> {
fn from(btree_set: &collections::BTreeSet<A>) -> Self {
btree_set.into_iter().cloned().collect()
}
}
impl<'a, A: Ord> From<&'a collections::BTreeSet<Arc<A>>> for OrdSet<A> {
fn from(btree_set: &collections::BTreeSet<Arc<A>>) -> Self {
btree_set.into_iter().cloned().collect()
}
}
impl<A: Ord, S> From<HashSet<A, S>> for OrdSet<A> {
fn from(hashset: HashSet<A, S>) -> Self {
hashset.into_iter().collect()
}
}
impl<'a, A: Ord, S> From<&'a HashSet<A, S>> for OrdSet<A> {
fn from(hashset: &HashSet<A, S>) -> Self {
hashset.into_iter().collect()
}
}
#[cfg(any(test, feature = "quickcheck"))]
use quickcheck::{Arbitrary, Gen};
#[cfg(any(test, feature = "quickcheck"))]
impl<A: Ord + Arbitrary + Sync> Arbitrary for OrdSet<A> {
fn arbitrary<G: Gen>(g: &mut G) -> Self {
OrdSet::from_iter(Vec::<A>::arbitrary(g))
}
}
#[cfg(any(test, feature = "proptest"))]
pub mod proptest {
use super::*;
use proptest::strategy::{BoxedStrategy, Strategy, ValueTree};
use std::ops::Range;
pub fn ord_set<A: Strategy + 'static>(
element: A,
size: Range<usize>,
) -> BoxedStrategy<OrdSet<<A::Value as ValueTree>::Value>>
where
<A::Value as ValueTree>::Value: Ord,
{
::proptest::collection::vec(element, size.clone())
.prop_map(OrdSet::from)
.prop_filter("OrdSet minimum size".to_owned(), move |s| {
s.len() >= size.start
})
.boxed()
}
}
#[cfg(test)]
mod test {
use super::proptest::*;
proptest! {
#[test]
fn proptest_a_set(ref s in ord_set(".*", 10..100)) {
assert!(s.len() < 100);
assert!(s.len() >= 10);
}
}
}