1#![allow(clippy::type_complexity)]
2
3use std::collections::BTreeMap;
4use std::fmt::Debug;
5use std::ops::Bound::{Included, Unbounded};
6
7pub struct ThresholdDict<K, V> {
8 tree: BTreeMap<K, V>,
9}
10
11impl<K: Ord, V> From<Vec<(K, V)>> for ThresholdDict<K, V> {
12 fn from(kv: Vec<(K, V)>) -> Self {
13 let tree = BTreeMap::from_iter(kv);
14 Self::new(tree)
15 }
16}
17
18impl<K: Ord, V> ThresholdDict<K, V> {
19 pub fn new(tree: BTreeMap<K, V>) -> Self {
21 Self { tree }
22 }
23
24 pub fn query(&self, key: &K) -> Option<&V> {
28 let query = (Included(key), Unbounded);
29 let result = self.tree.range(query).next();
30 result.map(|(_, v)| v)
31 }
32}
33
34impl<K: Ord + Clone, V: Clone> Clone for ThresholdDict<K, V> {
35 fn clone(&self) -> Self {
36 Self {
37 tree: self.tree.clone(),
38 }
39 }
40}
41
42impl<K: Ord + Debug, V: Debug> Debug for ThresholdDict<K, V> {
43 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
44 f.debug_struct("ThresholdDict")
45 .field("tree", &self.tree)
46 .finish()
47 }
48}
49
50#[cfg(test)]
51mod test {
52 use std::collections::BTreeMap;
53
54 use super::ThresholdDict;
55
56 #[test]
57 fn test_from_btree_map() {
58 let map = BTreeMap::from([(10, 100), (20, 150), (50, 300)]);
59 let dict = ThresholdDict::new(map);
60 let correct_dict = ThresholdDict::from(vec![(10, 100), (20, 150), (50, 300)]);
61 assert_eq!(dict.tree, correct_dict.tree);
62 }
63
64 #[test]
65 fn test_clone() {
66 let dict = ThresholdDict::from(vec![(10, 100), (20, 150), (50, 300)]);
67 let dict2 = dict.clone();
68 assert_eq!(dict.tree, dict2.tree);
69 }
70
71 #[test]
72 fn test_query() {
73 let dict = ThresholdDict::from(vec![(10, 100), (20, 150), (50, 300)]);
74 assert_eq!(dict.query(&0), Some(&100));
75 assert_eq!(dict.query(&10), Some(&100));
76 assert_eq!(dict.query(&15), Some(&150));
77 assert_eq!(dict.query(&40), Some(&300));
78 assert_eq!(dict.query(&50), Some(&300));
79 assert_eq!(dict.query(&60), None);
80 }
81}