rustogram 0.1.4

A rust port of HdrHistogram
Documentation
use std::fmt;
use histogram::*;

#[derive(PartialEq)]
pub struct HistogramIterationValue {
    value_iterated_to: i64,
    value_iterated_from: i64,
    count_at_value_iterated_to: i64,
    count_added_in_this_iteration_step: i64,
    total_count_to_this_value: i64,
    total_value_to_this_value: i64,
    percentile: f64,
    percentile_level_iterated_to: f64,
}

impl HistogramIterationValue {
    pub fn new() -> HistogramIterationValue {
        HistogramIterationValue {
            value_iterated_to: 0,
            value_iterated_from: 0,
            count_at_value_iterated_to: 0,
            count_added_in_this_iteration_step: 0,
            total_count_to_this_value: 0,
            total_value_to_this_value: 0,
            percentile: 0.0,
            percentile_level_iterated_to: 0.0,
        }
    }

    fn set(&mut self,
           _value_iterated_to: i64,
           _value_iterated_from: i64,
           _count_at_value_iterated_to: i64,
           _count_added_in_this_iteration_step: i64,
           _total_count_to_this_value: i64,
           _total_value_to_this_value: i64,
           _percentile: f64,
           _percentile_level_iterated_to: f64) {
        self.value_iterated_to = _value_iterated_to;
        self.value_iterated_from = _value_iterated_from;
        self.count_at_value_iterated_to = _count_at_value_iterated_to;
        self.count_added_in_this_iteration_step = _count_added_in_this_iteration_step;
        self.total_count_to_this_value = _total_count_to_this_value;
        self.total_value_to_this_value = _total_value_to_this_value;
        self.percentile = _percentile;
        self.percentile_level_iterated_to = _percentile_level_iterated_to;
    }

    fn reset(&mut self) {
        self.value_iterated_to = 0;
        self.value_iterated_from = 0;
        self.count_at_value_iterated_to = 0;
        self.count_added_in_this_iteration_step = 0;
        self.total_count_to_this_value = 0;
        self.total_value_to_this_value = 0;
        self.percentile = 0.0;
        self.percentile_level_iterated_to = 0.0;
    }

    pub fn copy_to(&self, target: &mut HistogramIterationValue) {
        target.value_iterated_to = self.value_iterated_to;
        target.value_iterated_from = self.value_iterated_from;
        target.count_at_value_iterated_to = self.count_at_value_iterated_to;
        target.count_added_in_this_iteration_step = self.count_added_in_this_iteration_step;
        target.total_count_to_this_value = self.total_count_to_this_value;
        target.total_value_to_this_value = self.total_value_to_this_value;
        target.percentile = self.percentile;
        target.percentile_level_iterated_to = self.percentile_level_iterated_to;
    }

    pub fn get_value_iterated_to(&self) -> i64 {
        self.value_iterated_to
    }

    pub fn get_count_at_value_iterated_to(&self) -> i64 {
        self.count_at_value_iterated_to
    }

    pub fn get_count_added_in_this_iteration_step(&self) -> i64 {
        self.count_added_in_this_iteration_step
    }

    pub fn get_total_value_to_this_value(&self) -> i64 {
        self.total_value_to_this_value
    }

    pub fn get_total_count_to_this_value(&self) -> i64 {
        self.total_count_to_this_value
    }
}

struct IteratorSharedState {
    saved_histogram_total_raw_count: i64,
    current_index: i32,
    current_value_at_index: i64,
    next_value_at_index: i64,
    prev_value_iterated_to: i64,
    total_count_to_prev_index: i64,
    total_count_to_current_index: i64,
    total_value_to_current_index: i64,
    array_total_count: i64,
    count_at_this_value: i64,
    fresh_sub_bucket: bool,
    visited_index: i32,
    current_iteration_value: HistogramIterationValue,
}

impl IteratorSharedState {
    fn exhausted_sub_buckets(&self, histogram: &Histogram) -> bool {
        self.current_index >= histogram.get_counts_array_length()
    }
    
    fn reset(&mut self, total_count: i64, unit_magnitude: i32) {
        self.saved_histogram_total_raw_count = total_count;
        self.array_total_count = total_count;
        self.current_index = 0;
        self.current_value_at_index = 0;
        self.next_value_at_index = 1 << unit_magnitude;
        self.prev_value_iterated_to = 0;
        self.total_count_to_prev_index = 0;
        self.total_count_to_current_index = 0;
        self.total_value_to_current_index = 0;
        self.count_at_this_value = 0;
        self.fresh_sub_bucket = true;
        self.visited_index = -1;
        self.current_iteration_value.reset();
    }
    
    fn get_percentile_iterated_to(&self) -> f64 {
        (100.0f64 * self.total_count_to_current_index as f64) / self.array_total_count as f64
    }
    
    fn get_value_iterated_to(&self, histogram: &Histogram) -> i64 {
        histogram.highest_equivalent_value(self.current_value_at_index)
    }

    fn increment_iteration_level(&mut self) {
        self.visited_index = self.current_index;
    }
    
    fn increment_sub_bucket(&mut self, histogram: &Histogram) {
        self.fresh_sub_bucket = true;
        self.current_index += 1;
        self.current_value_at_index = histogram.value_from_index(self.current_index);
        self.next_value_at_index = histogram.value_from_index(self.current_index + 1);
    }
    
    fn next<F>(&mut self, histogram: &Histogram, level_reached_function: F) -> &HistogramIterationValue 
    		where F: Fn(&mut IteratorSharedState, &Histogram) -> bool {
        while !self.exhausted_sub_buckets(histogram) {
            self.count_at_this_value = histogram.get_count_at_index(self.current_index);
            if self.fresh_sub_bucket {
                self.total_count_to_current_index += self.count_at_this_value;
                self.total_value_to_current_index +=
                    self.count_at_this_value *
                    histogram.highest_equivalent_value(self.current_value_at_index);
                self.fresh_sub_bucket = false;
            }

            if level_reached_function(self, histogram) {
                let value_iterated_to = self.get_value_iterated_to(histogram);
                let percentile_iterated_to = self.get_percentile_iterated_to();
                self.current_iteration_value.set(value_iterated_to,
                                                 self.prev_value_iterated_to,
                                                 self.count_at_this_value,
                                                 (self.total_count_to_current_index -
                                                  self.total_count_to_prev_index),
                                                 self.total_count_to_current_index,
                                                 self.total_value_to_current_index,
                                                 ((100.0f64 *
                                                   self.total_count_to_current_index as f64) /
                                                  (self.array_total_count as f64)),
                                                 percentile_iterated_to);
                self.prev_value_iterated_to = value_iterated_to;
                self.total_count_to_prev_index = self.total_count_to_current_index;
                self.increment_iteration_level();

                return &self.current_iteration_value;
            }

            self.increment_sub_bucket(histogram);
        }
        panic!("Histogram may have overflowed!")
    }
}

pub struct AllValuesIterator<'a> {
    histogram: &'a Histogram,
    state: IteratorSharedState
}

pub fn new_all_values_iterator<'a>(_histogram: &'a Histogram) -> AllValuesIterator {
    AllValuesIterator {
        histogram: _histogram,
        state: IteratorSharedState {
	        saved_histogram_total_raw_count: 0,
	        current_index: 0,
	        current_value_at_index: 0,
	        next_value_at_index: 0,
	        prev_value_iterated_to: 0,
	        total_count_to_prev_index: 0,
	        total_count_to_current_index: 0,
	        total_value_to_current_index: 0,
	        array_total_count: 0,
	        count_at_this_value: 0,
	        fresh_sub_bucket: true,
	        visited_index: -1,
	        current_iteration_value: HistogramIterationValue::new(),
        }
    }
}

impl<'a> AllValuesIterator<'a> {
    pub fn has_next(&mut self) -> bool {
        self.state.current_index < (self.histogram.get_counts_array_length() - 1)
    }

    pub fn reset(&mut self, total_count: i64, unit_magnitude: i32) {
        self.state.reset(total_count, unit_magnitude);
    }

    pub fn next(&mut self) -> &HistogramIterationValue {
    	self.state.next(self.histogram, |iterator_state: &mut IteratorSharedState, _histogram: &Histogram| {
    			iterator_state.visited_index != iterator_state.current_index
    	})
    }
}


pub struct RecordedValuesIterator<'a> {
    histogram: &'a Histogram,
    state: IteratorSharedState
}

pub fn new_iterator<'a>(_histogram: &'a Histogram) -> RecordedValuesIterator {
    RecordedValuesIterator {
        histogram: _histogram,
        state: IteratorSharedState {
	        saved_histogram_total_raw_count: 0,
	        current_index: 0,
	        current_value_at_index: 0,
	        next_value_at_index: 0,
	        prev_value_iterated_to: 0,
	        total_count_to_prev_index: 0,
	        total_count_to_current_index: 0,
	        total_value_to_current_index: 0,
	        array_total_count: 0,
	        count_at_this_value: 0,
	        fresh_sub_bucket: true,
	        visited_index: -1,
	        current_iteration_value: HistogramIterationValue::new(),
        }
    }
}

impl<'a> RecordedValuesIterator<'a> {
    pub fn has_next(&mut self) -> bool {
        self.state.total_count_to_current_index < self.state.array_total_count
    }
    
    pub fn reset(&mut self, total_count: i64, unit_magnitude: i32) {
        self.state.reset(total_count, unit_magnitude);
    }

    pub fn next(&mut self) -> &HistogramIterationValue {
    	self.state.next(self.histogram, |iterator_state: &mut IteratorSharedState, histogram: &Histogram| {
	        let current_count = histogram.get_count_at_index(iterator_state.current_index);
    	    (current_count != 0) && (iterator_state.visited_index != iterator_state.current_index)
    	})
    }
}

impl fmt::Display for HistogramIterationValue {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        try!(write!(f, "Value["));
        try!(write!(f, "value_iterated_to: {}, ", self.value_iterated_to));
        try!(write!(f, "value_iterated_from: {}, ", self.value_iterated_from));
        try!(write!(f,
                    "count_at_value_iterated_to: {}, ",
                    self.count_at_value_iterated_to));
        try!(write!(f,
                    "count_added_in_this_iteration_step: {}, ",
                    self.count_added_in_this_iteration_step));
        try!(write!(f,
                    "total_count_to_this_value: {}, ",
                    self.total_count_to_this_value));
        try!(write!(f,
                    "total_value_to_this_value: {}, ",
                    self.total_value_to_this_value));
        try!(write!(f, "percentile: {}, ", self.percentile));
        try!(write!(f,
                    "percentile_level_iterated_to: {}, ",
                    self.percentile_level_iterated_to));

        write!(f, "]")
    }
}