#[derive(Clone, Debug, Eq, PartialEq)]
pub struct ChangeBatch<T> {
updates: Vec<(T, i64)>,
clean: usize,
}
impl<T:Ord> ChangeBatch<T> {
pub fn new() -> ChangeBatch<T> {
ChangeBatch {
updates: Vec::new(),
clean: 0
}
}
pub fn new_from(key: T, val: i64) -> ChangeBatch<T> {
let mut result = ChangeBatch::new();
result.update(key, val);
result
}
pub fn is_dirty(&self) -> bool {
self.updates.len() > self.clean
}
#[inline]
pub fn update(&mut self, item: T, value: i64) {
self.updates.push((item, value));
self.maintain_bounds();
}
#[inline]
pub fn extend<I: Iterator<Item=(T, i64)>>(&mut self, iterator: I) {
self.updates.extend(iterator);
self.maintain_bounds();
}
pub fn into_inner(mut self) -> Vec<(T, i64)> {
self.compact();
self.updates
}
#[inline]
pub fn iter(&mut self) -> ::std::slice::Iter<(T, i64)> {
self.compact();
self.updates.iter()
}
#[inline]
pub fn drain(&mut self) -> ::std::vec::Drain<(T, i64)> {
self.compact();
self.clean = 0;
self.updates.drain(..)
}
#[inline]
pub fn clear(&mut self) {
self.updates.clear();
self.clean = 0;
}
#[inline]
pub fn is_empty(&mut self) -> bool {
if self.clean > self.updates.len() / 2 {
false
}
else {
self.compact();
self.updates.is_empty()
}
}
#[deprecated(since="0.9.0", note="please use `compact` instead")]
pub fn canonicalize(&mut self) {
self.compact();
self.updates.sort_by(|x,y| x.0.cmp(&y.0));
}
#[inline]
pub fn drain_into(&mut self, other: &mut ChangeBatch<T>) where T: Clone {
if other.updates.is_empty() {
::std::mem::swap(self, other);
}
else {
other.extend(self.updates.drain(..));
self.clean = 0;
}
}
#[inline]
pub fn compact(&mut self) {
if self.clean < self.updates.len() && self.updates.len() > 1 {
self.updates.sort_by(|x,y| x.0.cmp(&y.0));
for i in 0 .. self.updates.len() - 1 {
if self.updates[i].0 == self.updates[i+1].0 {
self.updates[i+1].1 += self.updates[i].1;
self.updates[i].1 = 0;
}
}
self.updates.retain(|x| x.1 != 0);
}
self.clean = self.updates.len();
}
pub fn unstable_internal_updates(&self) -> &Vec<(T, i64)> { &self.updates }
pub fn unstable_internal_clean(&self) -> usize { self.clean }
fn maintain_bounds(&mut self) {
if self.updates.len() > 32 && self.updates.len() >> 1 >= self.clean {
self.compact()
}
}
}