<commit_before>use std::time::Duration;
use std::thread;

/// BackoffTimer implements a timer that waits a certain amount and then backs off
/// until the configured max_wait_time (specified in seconds) is reached or passed.
///
/// Different specific timers implement their own version of back algorithms
pub trait BackoffTimer {
    fn wait(&mut self) -> u64;
    fn is_done(&self) -> bool;
}

/// ```
/// use backoff_timer::BackoffTimer;
/// use backoff_timer::exponential_backoff_timer;
///
/// let mut timer = exponential_backoff_timer(5);
/// let mut waited = timer.wait();
/// assert_eq!(waited, 2);
/// assert_eq!(timer.is_done(), false);
/// waited = timer.wait();
/// assert_eq!(waited, 4);
/// assert_eq!(timer.is_done(), true);
/// ```
pub struct ExponentialBackoffTimer {
    waited_time:   u64,
    wait_time:     u64,
    max_wait_time: u64,
}

/// new returns a new ExponentialBackoffTimer configured with the passed in max_wait_time in seconds
pub fn exponential_backoff_timer(max_wait_time: u64) -> ExponentialBackoffTimer {
    ExponentialBackoffTimer {
        max_wait_time: max_wait_time,
        wait_time: 2,
        waited_time: 0,
    }
}


impl BackoffTimer for ExponentialBackoffTimer {

    /// wait is a blocking function that waits for the appropriate amount of time depending on the
    /// timers internal state. It returns the time waited which is 0 if the timer has reached its
    /// max_wait_time
    fn wait(&mut self) -> u64 {
        if self.is_done() {
            return 0;
        }
        thread::sleep(Duration::from_secs(self.wait_time));
        let time_waited = self.wait_time;
        self.wait_time = self.wait_time.pow(2);
        self.waited_time = self.waited_time + self.wait_time;

        return time_waited;
    }

    /// is_done is a helper method to determine whether the timer is done or still has turns to
    /// wait.
    fn is_done(&self) -> bool {
        self.waited_time >= self.max_wait_time
    }

}



#[cfg(test)]
mod tests {
    use super::BackoffTimer;
    use super::exponential_backoff_timer;

    #[test]
    fn wait_for_5_seconds() {
        let mut timer = exponential_backoff_timer(5);
        let mut waited = timer.wait();
        assert_eq!(waited, 2);
        assert_eq!(timer.is_done(), false);<commit_msg>make the constructor part of the trait<commit_after>use std::time::Duration;
use std::thread;

/// BackoffTimer implements a timer that waits a certain amount and then backs off
/// until the configured max_wait_time (specified in seconds) is reached or passed.
///
/// Different specific timers implement their own version of back algorithms
pub trait BackoffTimer {
    fn wait(&mut self) -> u64;
    fn is_done(&self) -> bool;
    fn new(u64) -> Self;
}

/// ```
/// use backoff_timer::BackoffTimer;
/// use backoff_timer::ExponentialBackoffTimer;
///
/// let mut timer = ExponentialBackoffTimer::new(5);
/// let mut waited = timer.wait();
/// assert_eq!(waited, 2);
/// assert_eq!(timer.is_done(), false);
/// waited = timer.wait();
/// assert_eq!(waited, 4);
/// assert_eq!(timer.is_done(), true);
/// ```
pub struct ExponentialBackoffTimer {
    waited_time:   u64,
    wait_time:     u64,
    max_wait_time: u64,
}

impl BackoffTimer for ExponentialBackoffTimer {

    /// new returns a new ExponentialBackoffTimer configured with the passed in max_wait_time in seconds
    fn new(max_wait_time: u64) -> ExponentialBackoffTimer {
        ExponentialBackoffTimer {
            max_wait_time: max_wait_time,
            wait_time: 2,
            waited_time: 0,
        }
    }



    /// wait is a blocking function that waits for the appropriate amount of time depending on the
    /// timers internal state. It returns the time waited which is 0 if the timer has reached its
    /// max_wait_time
    fn wait(&mut self) -> u64 {
        if self.is_done() {
            return 0;
        }
        thread::sleep(Duration::from_secs(self.wait_time));
        let time_waited = self.wait_time;
        self.wait_time = self.wait_time.pow(2);
        self.waited_time = self.waited_time + self.wait_time;

        return time_waited;
    }

    /// is_done is a helper method to determine whether the timer is done or still has turns to
    /// wait.
    fn is_done(&self) -> bool {
        self.waited_time >= self.max_wait_time
    }

}



#[cfg(test)]
mod tests {
    use super::BackoffTimer;
    use super::ExponentialBackoffTimer;

    #[test]
    fn wait_for_5_seconds() {
        let mut timer = ExponentialBackoffTimer::new(5);
        let mut waited = timer.wait();
        assert_eq!(waited, 2);
        assert_eq!(timer.is_done(), false);
{'fraction_non_alphanumeric': 0.11555842479018721, 'fraction_numerical': 0.010329244673983214, 'mean_word_length': 2.8223684210526314, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 16, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1585076', 'n_tokens_mistral': 1462, 'n_tokens_neox': 1421, 'n_words': 419}