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
/// A map that stores values and thresholds that determine what value belongs to any given number.
#[derive(Debug, Clone)]
pub struct ThresholdMap<T> {
thresholds: Vec<u64>,
values: Vec<T>,
}
impl<T> ThresholdMap<T> {
/// A map that will return the same value for any input.
pub fn single_value<I: Into<T>>(value: I) -> Self {
Self::with_capacity(0, value.into())
}
/// Capacity is the number of thresholds (excluding the ever-present virtual 0 threshold), which is one less than the number of values.
pub fn with_capacity(capacity: usize, lowest_value: T) -> Self {
let thresholds = Vec::with_capacity(capacity);
let mut values = Vec::with_capacity(capacity + 1);
values.push(lowest_value);
Self { thresholds, values }
}
/// Creates a new `ThresholdMap` from an iterator yielding thresholds and values applying at or over those thresholds.
///
/// The lowest value is essentially the value for threshold 0.
///
/// Requires that all the thresholds in the iterator are in order, and fails if that is not the case.
///
/// ```
/// # use stringify_interval::ThresholdMap;
/// #
/// let map = ThresholdMap::<String>::from_iter("years", [(1, "year"), (2, "years")]).unwrap();
/// assert_eq!(map.get(25), &String::from("years")); // Or any value other than 1.
/// assert_eq!(map.get(1), &String::from("year"));
/// ```
pub fn from_iter<V: Into<T>>(
lowest_value: V,
iter: impl IntoIterator<Item = (u64, V)>,
) -> Option<Self> {
let iter = iter.into_iter();
let mut map = Self::with_capacity(iter.size_hint().1.unwrap_or(0), lowest_value.into());
for (threshold, value) in iter {
if !map.push(threshold, value.into()) {
return None;
}
}
Some(map)
}
/// Insert a new threshold and value to apply at and beyond that threshold.
///
/// Fails if the threshold was already in the map. Returns whether it succeeded.
pub fn insert(&mut self, threshold: u64, value: T) -> bool {
let Err(index) = self.get_index(&threshold) else {
return false;
};
self.thresholds.insert(index, threshold);
self.values.insert(index + 1, value);
true
}
/// Pushes a new threshold to the end of the list, and the value to apply at and beyond that threshold.
///
/// Fails if the threshold was not larger than the last threshold. Returns whether it succeeded.
pub fn push(&mut self, threshold: u64, value: T) -> bool {
if let Some(last) = self.thresholds.last() {
if *last >= threshold {
return false;
}
}
self.thresholds.push(threshold);
self.values.push(value);
true
}
/// Gets the value associated with the first threshold crossed, or the first one, since the virtual threshold of 0 is always crossed.
pub fn get(&self, key: u64) -> &T {
let index = self
.thresholds
.iter()
.position(|&threshold| key < threshold)
.unwrap_or(self.thresholds.len());
&self.values[index]
}
fn get_index(&self, key: &u64) -> Result<usize, usize> {
self.thresholds.binary_search(key)
}
}