use std::hash::Hash;
use std::collections::{HashSet, BTreeSet};
pub trait Collection<T> {
fn push(&mut self, elem: T);
fn extend_from_slice(&mut self, elems: &[T]) where T: Clone;
fn extend<I>(&mut self, elems: I) where I: IntoIterator<Item=T>;
fn reserve(&mut self, _size: usize) { }
}
impl<T> Collection<T> for Vec<T> {
fn push(&mut self, elem: T) {
Vec::push(self, elem);
}
fn extend_from_slice(&mut self, elems: &[T]) where T: Clone {
Vec::extend_from_slice(self, elems);
}
fn extend<I>(&mut self, elems: I) where I: IntoIterator<Item=T> {
Extend::extend(self, elems);
}
fn reserve(&mut self, size: usize) {
Vec::reserve(self, size);
}
}
impl<T: Hash + Eq> Collection<T> for HashSet<T> {
fn push(&mut self, elem: T) {
HashSet::insert(self, elem);
}
fn extend_from_slice(&mut self, elems: &[T]) where T: Clone {
Collection::extend(self, elems.iter().cloned());
}
fn extend<I>(&mut self, elems: I) where I: IntoIterator<Item=T> {
Extend::extend(self, elems);
}
fn reserve(&mut self, size: usize) {
HashSet::reserve(self, size);
}
}
impl<T: Ord> Collection<T> for BTreeSet<T> {
fn push(&mut self, elem: T) {
BTreeSet::insert(self, elem);
}
fn extend_from_slice(&mut self, elems: &[T]) where T: Clone {
Collection::extend(self, elems.iter().cloned());
}
fn extend<I>(&mut self, elems: I) where I: IntoIterator<Item=T> {
Extend::extend(self, elems);
}
}
#[derive(Default)]
pub struct Counter(pub usize);
impl Counter {
pub fn new() -> Counter {
Counter::default()
}
}
impl<T> Collection<T> for Counter {
fn push(&mut self, _elem: T) {
self.0 = self.0.saturating_add(1);
}
fn extend_from_slice(&mut self, elems: &[T]) where T: Clone {
self.0 = self.0.saturating_add(elems.len());
}
fn extend<I>(&mut self, elems: I) where I: IntoIterator<Item=T> {
self.0 = self.0.saturating_add(elems.into_iter().count());
}
}