#![cfg_attr(feature = "nightly", feature(ptr_offset_from))]
#![cfg_attr(feature = "nightly", feature(test))]
#![cfg_attr(all(not(test), not(feature = "std")), no_std)]
#[cfg(all(not(test), not(feature = "std")))]
extern crate core as std;
macro_rules! group_by_wrapped {
(struct $name:ident, $elem:ty) => {
impl<'a, T: 'a> std::iter::Iterator for $name<'a, T>
where T: PartialEq,
{
type Item = $elem;
fn next(&mut self) -> Option<Self::Item> {
self.0.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.0.size_hint()
}
fn last(self) -> Option<Self::Item> {
self.0.last()
}
}
impl<'a, T: 'a> DoubleEndedIterator for $name<'a, T>
where T: PartialEq,
{
fn next_back(&mut self) -> Option<Self::Item> {
self.0.next_back()
}
}
impl<'a, T: 'a> std::iter::FusedIterator for $name<'a, T>
where T: PartialEq,
{ }
}
}
mod linear_group;
mod binary_group;
mod exponential_group;
mod linear_str_group;
use std::cmp::{self, Ordering};
pub use self::linear_group::{
LinearGroupByKey,
LinearGroupBy,
LinearGroup,
LinearGroupByKeyMut,
LinearGroupByMut,
LinearGroupMut,
};
pub use self::binary_group::{
BinaryGroupByKey,
BinaryGroupBy,
BinaryGroup,
BinaryGroupByKeyMut,
BinaryGroupByMut,
BinaryGroupMut,
};
pub use self::exponential_group::{
ExponentialGroupByKey,
ExponentialGroupBy,
ExponentialGroup,
ExponentialGroupByKeyMut,
ExponentialGroupByMut,
ExponentialGroupMut,
};
pub use self::linear_str_group::{
LinearStrGroupByKey,
LinearStrGroupBy,
LinearStrGroup,
LinearStrGroupByKeyMut,
LinearStrGroupByMut,
LinearStrGroupMut,
};
#[cfg(feature = "nightly")]
#[inline]
unsafe fn offset_from<T>(to: *const T, from: *const T) -> usize {
to.offset_from(from) as usize
}
#[cfg(not(feature = "nightly"))]
#[inline]
unsafe fn offset_from<T>(to: *const T, from: *const T) -> usize {
use std::mem;
(to as usize - from as usize) / mem::size_of::<T>()
}
#[inline]
pub fn exponential_search<T>(slice: &[T], elem: &T) -> Result<usize, usize>
where T: Ord
{
exponential_search_by(slice, |x| x.cmp(elem))
}
#[inline]
pub fn exponential_search_by<T, F>(slice: &[T], mut f: F) -> Result<usize, usize>
where F: FnMut(&T) -> Ordering,
{
let mut index = 1;
while index < slice.len() && f(&slice[index]) == Ordering::Less {
index *= 2;
}
let half_bound = index / 2;
let bound = cmp::min(index + 1, slice.len());
match slice[half_bound..bound].binary_search_by(f) {
Ok(pos) => Ok(half_bound + pos),
Err(pos) => Err(half_bound + pos),
}
}
#[inline]
pub fn exponential_search_by_key<T, B, F>(slice: &[T], b: &B, mut f: F) -> Result<usize, usize>
where F: FnMut(&T) -> B,
B: Ord
{
exponential_search_by(slice, |k| f(k).cmp(b))
}
pub trait GroupBy<T>
{
fn linear_group_by_key<F, K>(&self, func: F) -> LinearGroupByKey<T, F>
where F: FnMut(&T) -> K,
K: PartialEq;
fn linear_group_by<P>(&self, predicate: P) -> LinearGroupBy<T, P>
where P: FnMut(&T, &T) -> bool;
fn linear_group(&self) -> LinearGroup<T>
where T: PartialEq;
fn binary_group_by_key<F, K>(&self, func: F) -> BinaryGroupByKey<T, F>
where F: FnMut(&T) -> K,
K: PartialEq;
fn binary_group_by<P>(&self, predicate: P) -> BinaryGroupBy<T, P>
where P: FnMut(&T, &T) -> bool;
fn binary_group(&self) -> BinaryGroup<T>
where T: PartialEq;
fn exponential_group_by_key<F, K>(&self, func: F) -> ExponentialGroupByKey<T, F>
where F: Fn(&T) -> K,
K: PartialEq;
fn exponential_group_by<P>(&self, predicate: P) -> ExponentialGroupBy<T, P>
where P: FnMut(&T, &T) -> bool;
fn exponential_group(&self) -> ExponentialGroup<T>
where T: PartialEq;
}
pub trait GroupByMut<T>
{
fn linear_group_by_key_mut<F, K>(&mut self, func: F) -> LinearGroupByKeyMut<T, F>
where F: FnMut(&T) -> K,
K: PartialEq;
fn linear_group_by_mut<P>(&mut self, predicate: P) -> LinearGroupByMut<T, P>
where P: FnMut(&T, &T) -> bool;
fn linear_group_mut(&mut self) -> LinearGroupMut<T>
where T: PartialEq;
fn binary_group_by_key_mut<F, K>(&mut self, func: F) -> BinaryGroupByKeyMut<T, F>
where F: FnMut(&T) -> K,
K: PartialEq;
fn binary_group_by_mut<P>(&mut self, predicate: P) -> BinaryGroupByMut<T, P>
where P: FnMut(&T, &T) -> bool;
fn binary_group_mut(&mut self) -> BinaryGroupMut<T>
where T: PartialEq;
fn exponential_group_by_key_mut<F, K>(&mut self, func: F) -> ExponentialGroupByKeyMut<T, F>
where F: Fn(&T) -> K,
K: PartialEq;
fn exponential_group_by_mut<P>(&mut self, predicate: P) -> ExponentialGroupByMut<T, P>
where P: FnMut(&T, &T) -> bool;
fn exponential_group_mut(&mut self) -> ExponentialGroupMut<T>
where T: PartialEq;
}
impl<T> GroupBy<T> for [T]
{
fn linear_group_by_key<F, K>(&self, func: F) -> LinearGroupByKey<T, F>
where F: FnMut(&T) -> K,
K: PartialEq
{
LinearGroupByKey::new(self, func)
}
fn linear_group_by<P>(&self, predicate: P) -> LinearGroupBy<T, P>
where P: FnMut(&T, &T) -> bool,
{
LinearGroupBy::new(self, predicate)
}
fn linear_group(&self) -> LinearGroup<T>
where T: PartialEq,
{
LinearGroup::new(self)
}
fn binary_group_by_key<F, K>(&self, func: F) -> BinaryGroupByKey<T, F>
where F: FnMut(&T) -> K,
K: PartialEq
{
BinaryGroupByKey::new(self, func)
}
fn binary_group_by<P>(&self, predicate: P) -> BinaryGroupBy<T, P>
where P: FnMut(&T, &T) -> bool,
{
BinaryGroupBy::new(self, predicate)
}
fn binary_group(&self) -> BinaryGroup<T>
where T: PartialEq,
{
BinaryGroup::new(self)
}
fn exponential_group_by_key<F, K>(&self, func: F) -> ExponentialGroupByKey<T, F>
where F: Fn(&T) -> K,
K: PartialEq
{
ExponentialGroupByKey::new(self, func)
}
fn exponential_group_by<P>(&self, predicate: P) -> ExponentialGroupBy<T, P>
where P: FnMut(&T, &T) -> bool,
{
ExponentialGroupBy::new(self, predicate)
}
fn exponential_group(&self) -> ExponentialGroup<T>
where T: PartialEq,
{
ExponentialGroup::new(self)
}
}
impl<T> GroupByMut<T> for [T]
{
fn linear_group_by_key_mut<F, K>(&mut self, func: F) -> LinearGroupByKeyMut<T, F>
where F: FnMut(&T) -> K,
K: PartialEq
{
LinearGroupByKeyMut::new(self, func)
}
fn linear_group_by_mut<P>(&mut self, predicate: P) -> LinearGroupByMut<T, P>
where P: FnMut(&T, &T) -> bool,
{
LinearGroupByMut::new(self, predicate)
}
fn linear_group_mut(&mut self) -> LinearGroupMut<T>
where T: PartialEq,
{
LinearGroupMut::new(self)
}
fn binary_group_by_key_mut<F, K>(&mut self, func: F) -> BinaryGroupByKeyMut<T, F>
where F: FnMut(&T) -> K,
K: PartialEq
{
BinaryGroupByKeyMut::new(self, func)
}
fn binary_group_by_mut<P>(&mut self, predicate: P) -> BinaryGroupByMut<T, P>
where P: FnMut(&T, &T) -> bool,
{
BinaryGroupByMut::new(self, predicate)
}
fn binary_group_mut(&mut self) -> BinaryGroupMut<T>
where T: PartialEq,
{
BinaryGroupMut::new(self)
}
fn exponential_group_by_key_mut<F, K>(&mut self, func: F) -> ExponentialGroupByKeyMut<T, F>
where F: Fn(&T) -> K,
K: PartialEq
{
ExponentialGroupByKeyMut::new(self, func)
}
fn exponential_group_by_mut<P>(&mut self, predicate: P) -> ExponentialGroupByMut<T, P>
where P: FnMut(&T, &T) -> bool,
{
ExponentialGroupByMut::new(self, predicate)
}
fn exponential_group_mut(&mut self) -> ExponentialGroupMut<T>
where T: PartialEq,
{
ExponentialGroupMut::new(self)
}
}
pub trait StrGroupBy
{
fn linear_group_by_key<F, K>(&self, func: F) -> LinearStrGroupByKey<F>
where F: FnMut(char) -> K,
K: PartialEq;
fn linear_group_by<P>(&self, predicate: P) -> LinearStrGroupBy<P>
where P: FnMut(char, char) -> bool;
fn linear_group(&self) -> LinearStrGroup;
}
pub trait StrGroupByMut
{
fn linear_group_by_key_mut<F, K>(&mut self, func: F) -> LinearStrGroupByKeyMut<F>
where F: FnMut(char) -> K,
K: PartialEq;
fn linear_group_by_mut<P>(&mut self, predicate: P) -> LinearStrGroupByMut<P>
where P: FnMut(char, char) -> bool;
fn linear_group_mut(&mut self) -> LinearStrGroupMut;
}
impl StrGroupBy for str
{
fn linear_group_by_key<F, K>(&self, func: F) -> LinearStrGroupByKey<F>
where F: FnMut(char) -> K,
K: PartialEq
{
LinearStrGroupByKey::new(self, func)
}
fn linear_group_by<P>(&self, predicate: P) -> LinearStrGroupBy<P>
where P: FnMut(char, char) -> bool,
{
LinearStrGroupBy::new(self, predicate)
}
fn linear_group(&self) -> LinearStrGroup {
LinearStrGroup::new(self)
}
}
impl StrGroupByMut for str
{
fn linear_group_by_key_mut<F, K>(&mut self, func: F) -> LinearStrGroupByKeyMut<F>
where F: FnMut(char) -> K,
K: PartialEq
{
LinearStrGroupByKeyMut::new(self, func)
}
fn linear_group_by_mut<P>(&mut self, predicate: P) -> LinearStrGroupByMut<P>
where P: FnMut(char, char) -> bool,
{
LinearStrGroupByMut::new(self, predicate)
}
fn linear_group_mut(&mut self) -> LinearStrGroupMut {
LinearStrGroupMut::new(self)
}
}