1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
//!
use std::fmt;
/// A little versatile Counter.
#[derive(Debug)]
pub struct Counter {
/// The starting value.
pub starting: isize,
/// The current value.
pub current: isize,
/// The amount to increase the current value on each
/// [`update`][Self#method.update], until it reaches its `limit`.
pub step: isize,
/// An optional *limit* value that, when reached, will prevent further
/// updating the counter.
///
/// If set, it must have the same sign as the `step`. If not set,
/// the natural limit will be |[`isize::MAX`]|.
pub limit: Option<isize>,
}
impl fmt::Display for Counter {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"[{1} {2:+} (from {0}{3})",
self.starting,
self.current,
self.step,
self.limit.map_or("".into(), |v| format![" to {}", v])
)
}
}
impl Counter {
/// Returns a new `Counter`.
///
/// Note that `limit` and `step` must be both positive or negative together.
pub fn new(value: isize, step: isize, limit: Option<isize>) -> Self {
if let Some(lim) = limit {
assert![(step < 0) == (lim < 0)];
}
Self { starting: value, current: value, step, limit }
}
/// If a `limit` value has been set, returns `true` when the counter has
/// reached its `limit` value, and if not, increments its `current` value.
///
/// If there's no `limit` value, always returns `false` while incrementing
/// the `current` value.
pub fn update(&mut self) -> bool {
let limit = if let Some(lim) = self.limit { lim.abs() } else { isize::MAX };
if self.current.abs() >= limit {
true
} else {
self.current += self.step;
false
}
}
/// Like [`update`] but wraps the value if it reaches the [`limit`].
///
/// [`update`]: Counter#method.update
/// [`limit`]: Counter#field.update
pub fn wrapping_update(&mut self) -> bool {
if self.update() {
self.reset();
true
} else {
false
}
}
/// Returns true if the counter has reached its `limit` value.
///
/// When there's no limit, it will always return `false`.
pub fn is_done(&self) -> bool {
if let Some(lim) = self.limit {
self.current >= lim
} else {
false
}
}
/// Returns the `current` value, and sets it at the `starting` value.
pub fn reset(&mut self) -> isize {
let old = self.current;
self.current = self.starting;
old
}
}
